mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: BAREBOX <barebox@lists.infradead.org>
Subject: [PATCH 15/27] gpio: pxa: add a driver and switch the architecture to GPIOLIB
Date: Sun, 16 Aug 2026 19:56:35 +0200	[thread overview]
Message-ID: <20260816-pxa3xx-v1-15-f3c3d7a6c43f@pengutronix.de> (raw)
In-Reply-To: <20260816-pxa3xx-v1-0-f3c3d7a6c43f@pengutronix.de>

PXA had no GPIO driver at all. ARCH_PXA selected GENERIC_GPIO, which on
PXA means arch/arm/mach-pxa/gpio.c: a handful of gpio_get_value() and
friends operating directly on the registers, but no gpio chip. So none
of the GPIOs described in the device tree could be used and every
consumer of them silently did nothing, be it the leds, the gpio keys,
the poweroff or the reset of the ethernet chip.

Add a proper driver for the device tree described controller and switch
the architecture over to GPIOLIB. The register layout is simple: banks
of 32 GPIOs, the first three interleaved one 32bit register per bank and
every further group of three starting at the next 0x100 boundary.

The old implementation has to go in the same step, its gpio_set_value()
and friends collide with the ones from gpiolib. Its only users were the
pxa_init_gpio() calls in the PXA2xx MFP code, which set up the gpio
range for that implementation and have no equivalent here: the range
comes from the device tree now.

Assisted-by: Claude Opus 5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/Kconfig           |   2 +-
 arch/arm/mach-pxa/Makefile |   1 -
 arch/arm/mach-pxa/gpio.c   | 101 -------------------------------
 drivers/gpio/Kconfig       |   6 ++
 drivers/gpio/Makefile      |   1 +
 drivers/gpio/gpio-pxa.c    | 146 +++++++++++++++++++++++++++++++++++++++++++++
 include/mach/pxa/gpio.h    |   1 -
 7 files changed, 154 insertions(+), 104 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fe4fd3f471..2f2ab5d76d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -121,7 +121,7 @@ config ARCH_MXS
 config ARCH_PXA
 	bool "Intel/Marvell PXA based"
 	depends on 32BIT
-	select GENERIC_GPIO
+	select GPIOLIB
 
 config ARCH_SOCFPGA
 	bool "Altera SOCFPGA"
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index b4f3a51046..fa0793d8a9 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,6 @@
 obj-y += clocksource.o
 obj-y += sleep.o
 obj-y += common.o
-obj-y += gpio.o
 obj-y += devices.o
 
 obj-$(CONFIG_ARCH_PXA3XX) += mfp-pxa3xx.o pxa3xx.o
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
deleted file mode 100644
index 130faa404b..0000000000
--- a/arch/arm/mach-pxa/gpio.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#include <common.h>
-#include <errno.h>
-#include <gpio.h>
-
-#include <mach/pxa/gpio.h>
-#include <asm/io.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	void __iomem	*regbase;
-};
-
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c) \
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32)
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-int __init pxa_init_gpio(int start, int end)
-{
-	struct pxa_gpio_chip *c;
-	int err,  gpio;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	err = pxa_init_gpio_chip(end);
-	if (err)
-		return err;
-
-	for_each_gpio_chip(gpio, c) {
-		/* clear all GPIO edge detects */
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0, c->regbase + GEDR_OFFSET);
-	}
-
-	return 0;
-}
-
-int gpio_get_value(unsigned gpio)
-{
-	return GPLR(gpio) & GPIO_bit(gpio);
-}
-
-void gpio_set_value(unsigned gpio, int value)
-{
-	if (value)
-		GPSR(gpio) = GPIO_bit(gpio);
-	else
-		GPCR(gpio) = GPIO_bit(gpio);
-}
-
-int gpio_direction_input(unsigned gpio)
-{
-	if (__gpio_is_inverted(gpio))
-		GPDR(gpio) |= GPIO_bit(gpio);
-	else
-		GPDR(gpio) &= ~GPIO_bit(gpio);
-	return 0;
-}
-
-int gpio_direction_output(unsigned gpio, int value)
-{
-	gpio_set_value(gpio, value);
-	if (__gpio_is_inverted(gpio))
-		GPDR(gpio) &= ~GPIO_bit(gpio);
-	else
-		GPDR(gpio) |= GPIO_bit(gpio);
-	return 0;
-}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 988d08cf14..923d424e62 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -163,6 +163,12 @@ config GPIO_PL061
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
 
+config GPIO_PXA
+	bool "GPIO support for Intel/Marvell PXA"
+	depends on ARCH_PXA || COMPILE_TEST
+	help
+	  Say yes here to enable the GPIO driver for the PXA SoCs
+
 config GPIO_RASPBERRYPI_EXP
 	bool "Raspberry Pi 3 GPIO Expander"
 	depends on ARCH_BCM283X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8560e1f059..38059a47f7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_JZ4740)	+= gpio-jz4740.o
 obj-$(CONFIG_GPIO_MALTA_FPGA_I2C) += gpio-malta-fpga-i2c.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_ORION)	+= gpio-orion.o
+obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_OMAP)		+= gpio-omap.o
 obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
new file mode 100644
index 0000000000..04b547a141
--- /dev/null
+++ b/drivers/gpio/gpio-pxa.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driver for the Intel/Marvell PXA SoCs
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <malloc.h>
+#include <of_device.h>
+
+/*
+ * The registers are grouped in banks of 32 GPIOs. The first three banks
+ * are interleaved, one 32bit register per bank, and every further group
+ * of three banks starts at the next 0x100 boundary.
+ */
+#define GPLR	0x00	/* pin level, read only */
+#define GPDR	0x0c	/* direction, 1 = output */
+#define GPSR	0x18	/* set output, write 1 to set */
+#define GPCR	0x24	/* clear output, write 1 to clear */
+
+#define BANK_OFF(bank)	((((bank) / 3) << 8) + (((bank) % 3) << 2))
+
+struct pxa_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem *base;
+};
+
+static inline struct pxa_gpio_chip *to_pxa_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct pxa_gpio_chip, chip);
+}
+
+static inline void __iomem *pxa_gpio_reg(struct gpio_chip *chip,
+					 unsigned off, unsigned reg)
+{
+	return to_pxa_gpio(chip)->base + BANK_OFF(off / 32) + reg;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned off)
+{
+	return !!(readl(pxa_gpio_reg(chip, off, GPLR)) & BIT(off % 32));
+}
+
+static int pxa_gpio_set(struct gpio_chip *chip, unsigned off, int value)
+{
+	writel(BIT(off % 32), pxa_gpio_reg(chip, off, value ? GPSR : GPCR));
+
+	return 0;
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+{
+	void __iomem *gpdr = pxa_gpio_reg(chip, off, GPDR);
+
+	writel(readl(gpdr) & ~BIT(off % 32), gpdr);
+
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip, unsigned off,
+				     int value)
+{
+	void __iomem *gpdr = pxa_gpio_reg(chip, off, GPDR);
+
+	/* drive the requested level before switching the pin to output */
+	pxa_gpio_set(chip, off, value);
+	writel(readl(gpdr) | BIT(off % 32), gpdr);
+
+	return 0;
+}
+
+static int pxa_gpio_get_direction(struct gpio_chip *chip, unsigned off)
+{
+	if (readl(pxa_gpio_reg(chip, off, GPDR)) & BIT(off % 32))
+		return GPIOF_DIR_OUT;
+
+	return GPIOF_DIR_IN;
+}
+
+static struct gpio_ops pxa_gpio_ops = {
+	.direction_input = pxa_gpio_direction_input,
+	.direction_output = pxa_gpio_direction_output,
+	.get_direction = pxa_gpio_get_direction,
+	.get = pxa_gpio_get,
+	.set = pxa_gpio_set,
+};
+
+static int pxa_gpio_probe(struct device *dev)
+{
+	struct pxa_gpio_chip *pxa;
+	struct resource *iores;
+	int ret;
+
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores))
+		return PTR_ERR(iores);
+
+	pxa = xzalloc(sizeof(*pxa));
+	pxa->base = IOMEM(iores->start);
+
+	pxa->chip.dev = dev;
+	pxa->chip.ops = &pxa_gpio_ops;
+	pxa->chip.base = 0;
+	pxa->chip.ngpio = (uintptr_t)device_get_match_data(dev);
+
+	ret = gpiochip_add(&pxa->chip);
+	if (ret) {
+		dev_err(dev, "couldn't add gpiochip: %pe\n", ERR_PTR(ret));
+		free(pxa);
+		return ret;
+	}
+
+	dev_dbg(dev, "probed %u gpios\n", pxa->chip.ngpio);
+
+	return 0;
+}
+
+static struct of_device_id pxa_gpio_dt_ids[] = {
+	{
+		.compatible = "intel,pxa25x-gpio",
+		.data = (void *)85,
+	}, {
+		.compatible = "intel,pxa26x-gpio",
+		.data = (void *)90,
+	}, {
+		.compatible = "intel,pxa27x-gpio",
+		.data = (void *)121,
+	}, {
+		.compatible = "intel,pxa3xx-gpio",
+		.data = (void *)128,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, pxa_gpio_dt_ids);
+
+static struct driver pxa_gpio_driver = {
+	.name = "pxa-gpio",
+	.probe = pxa_gpio_probe,
+	.of_compatible = DRV_OF_COMPAT(pxa_gpio_dt_ids),
+};
+core_platform_driver(pxa_gpio_driver);
diff --git a/include/mach/pxa/gpio.h b/include/mach/pxa/gpio.h
index 2d169608d8..84331f6b5c 100644
--- a/include/mach/pxa/gpio.h
+++ b/include/mach/pxa/gpio.h
@@ -133,6 +133,5 @@ static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
  */
 extern int pxa_last_gpio;
 
-extern int pxa_init_gpio(int start, int end);
 
 #endif

-- 
2.47.3




  parent reply	other threads:[~2026-08-16 18:02 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-16 17:56 [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Sascha Hauer
2026-08-16 17:56 ` [PATCH 01/27] ARM: pxa: remove PXA25x and PXA27x support Sascha Hauer
2026-08-16 17:56 ` [PATCH 02/27] video: remove the PXA framebuffer driver Sascha Hauer
2026-08-16 17:56 ` [PATCH 03/27] ARM: cache: drive the XSC3 cache with the ARMv4 functions Sascha Hauer
2026-08-16 17:56 ` [PATCH 04/27] mci: pxamci: get the clock from the clk API Sascha Hauer
2026-08-16 17:56 ` [PATCH 05/27] pwm: pxa: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 06/27] serial: " Sascha Hauer
2026-08-16 17:56 ` [PATCH 07/27] clk: pxa: add a device tree clock driver for PXA3xx Sascha Hauer
2026-08-16 17:56 ` [PATCH 08/27] mtd: nand: nand_mrvl_nfc: honour marvell,nand-keep-config Sascha Hauer
2026-08-16 17:56 ` [PATCH 09/27] mtd: nand: nand_mrvl_nfc: support the nand-controller bindings Sascha Hauer
2026-08-16 17:56 ` [PATCH 10/27] mtd: nand: mrvl_nfc: keep the ready latch across a STATUS command Sascha Hauer
2026-08-16 17:56 ` [PATCH 11/27] mtd: nand: mrvl_nfc: do not report a command timeout as an error Sascha Hauer
2026-08-16 17:56 ` [PATCH 12/27] mci: pxamci: probe from the device tree Sascha Hauer
2026-08-16 17:56 ` [PATCH 13/27] serial: pxa: add device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 14/27] serial: pxa: provide the Linux console name Sascha Hauer
2026-08-16 17:56 ` Sascha Hauer [this message]
2026-08-16 17:56 ` [PATCH 16/27] ARM: pxa: add DEBUG_LL support Sascha Hauer
2026-08-16 17:56 ` [PATCH 17/27] ARM: pxa: let the board select the SoC Sascha Hauer
2026-08-16 17:56 ` [PATCH 18/27] ARM: pxa: enable device tree support Sascha Hauer
2026-08-16 17:56 ` [PATCH 19/27] scripts: add pxa-image Sascha Hauer
2026-08-16 17:56 ` [PATCH 20/27] ARM: pxa: add a NAND first stage loader Sascha Hauer
2026-08-16 17:56 ` [PATCH 21/27] filetype: detect PXA3xx NTIM images Sascha Hauer
2026-08-16 17:56 ` [PATCH 22/27] ARM: pxa: add a barebox update handler for NAND Sascha Hauer
2026-08-16 17:56 ` [PATCH 23/27] clocksource: add a driver for the PXA OS timer and its watchdog Sascha Hauer
2026-08-16 17:56 ` [PATCH 24/27] ARM: pxa: move over to MULTIARCH Sascha Hauer
2026-08-16 17:56 ` [PATCH 25/27] ARM: pxa: reset straight away and without complaining Sascha Hauer
2026-08-16 17:56 ` [PATCH 26/27] ARM: pxa: add Raumfeld Speaker board support Sascha Hauer
2026-08-16 17:56 ` [PATCH 27/27] ARM: multi_v5_v6_defconfig: enable PXA support Sascha Hauer
2026-08-17  7:35 ` [PATCH 00/27] ARM: Add pxa3xx and Raumfeld Speaker support Ahmad Fatoum
2026-08-19  9:26 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260816-pxa3xx-v1-15-f3c3d7a6c43f@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox