From df868dcd8b11d5edba758eda5ffddbcf9cd6173e Mon Sep 17 00:00:00 2001
From: Dom Cobley <popcornmix@gmail.com>
Date: Tue, 14 Oct 2025 16:48:59 +0100
Subject: [PATCH] pinctrl: Reinstate the downstream pinctrl-rp1 driver

The upstream version has limited functionality.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

Fixup downstream pinctrl-rp1 driver
---
 drivers/pinctrl/pinctrl-rp1.c | 1297 ++++++++++++++-------------------
 1 file changed, 543 insertions(+), 754 deletions(-)

--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Driver for Raspberry Pi RP1 GPIO unit
+ * Driver for Raspberry Pi RP1 GPIO unit (pinctrl + GPIO)
  *
  * Copyright (C) 2023 Raspberry Pi Ltd.
  *
@@ -8,15 +8,31 @@
  * pinctrl-bcm2835.c, please see original file for copyright information
  */
 
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
 #include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_device.h>
 #include <linux/seq_file.h>
-#include <linux/regmap.h>
-
-#include "pinmux.h"
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include "core.h"
 #include "pinconf.h"
 #include "pinctrl-utils.h"
 
@@ -24,13 +40,60 @@
 #define RP1_NUM_GPIOS	54
 #define RP1_NUM_BANKS	3
 
+#define RP1_RW_OFFSET			0x0000
+#define RP1_XOR_OFFSET			0x1000
+#define RP1_SET_OFFSET			0x2000
+#define RP1_CLR_OFFSET			0x3000
+
+#define RP1_GPIO_STATUS			0x0000
+#define RP1_GPIO_CTRL			0x0004
+
+#define RP1_GPIO_PCIE_INTE		0x011c
+#define RP1_GPIO_PCIE_INTS		0x0124
+
+#define RP1_GPIO_EVENTS_SHIFT_RAW	20
+#define RP1_GPIO_STATUS_FALLING		BIT(20)
+#define RP1_GPIO_STATUS_RISING		BIT(21)
+#define RP1_GPIO_STATUS_LOW		BIT(22)
+#define RP1_GPIO_STATUS_HIGH		BIT(23)
+
+#define RP1_GPIO_EVENTS_SHIFT_FILTERED	24
+#define RP1_GPIO_STATUS_F_FALLING	BIT(24)
+#define RP1_GPIO_STATUS_F_RISING	BIT(25)
+#define RP1_GPIO_STATUS_F_LOW		BIT(26)
+#define RP1_GPIO_STATUS_F_HIGH		BIT(27)
+
+#define RP1_GPIO_CTRL_FUNCSEL_LSB	0
+#define RP1_GPIO_CTRL_FUNCSEL_MASK	0x0000001f
+#define RP1_GPIO_CTRL_OUTOVER_LSB	12
+#define RP1_GPIO_CTRL_OUTOVER_MASK	0x00003000
+#define RP1_GPIO_CTRL_OEOVER_LSB	14
+#define RP1_GPIO_CTRL_OEOVER_MASK	0x0000c000
+#define RP1_GPIO_CTRL_INOVER_LSB	16
+#define RP1_GPIO_CTRL_INOVER_MASK	0x00030000
+#define RP1_GPIO_CTRL_IRQEN_FALLING	BIT(20)
+#define RP1_GPIO_CTRL_IRQEN_RISING	BIT(21)
+#define RP1_GPIO_CTRL_IRQEN_LOW		BIT(22)
+#define RP1_GPIO_CTRL_IRQEN_HIGH	BIT(23)
+#define RP1_GPIO_CTRL_IRQEN_F_FALLING	BIT(24)
+#define RP1_GPIO_CTRL_IRQEN_F_RISING	BIT(25)
+#define RP1_GPIO_CTRL_IRQEN_F_LOW	BIT(26)
+#define RP1_GPIO_CTRL_IRQEN_F_HIGH	BIT(27)
+#define RP1_GPIO_CTRL_IRQRESET		BIT(28)
+#define RP1_GPIO_CTRL_IRQOVER_LSB	30
+#define RP1_GPIO_CTRL_IRQOVER_MASK	0xc0000000
+
 #define RP1_INT_EDGE_FALLING		BIT(0)
 #define RP1_INT_EDGE_RISING		BIT(1)
 #define RP1_INT_LEVEL_LOW		BIT(2)
 #define RP1_INT_LEVEL_HIGH		BIT(3)
-#define RP1_INT_MASK			GENMASK(3, 0)
+#define RP1_INT_MASK			0xf
+
 #define RP1_INT_EDGE_BOTH		(RP1_INT_EDGE_FALLING |	\
 					 RP1_INT_EDGE_RISING)
+#define RP1_PUD_OFF			0
+#define RP1_PUD_DOWN			1
+#define RP1_PUD_UP			2
 
 #define RP1_FSEL_COUNT			9
 
@@ -39,108 +102,48 @@
 #define RP1_FSEL_NONE			0x09
 #define RP1_FSEL_NONE_HW		0x1f
 
-#define RP1_PAD_DRIVE_2MA		0x0
-#define RP1_PAD_DRIVE_4MA		0x1
-#define RP1_PAD_DRIVE_8MA		0x2
-#define RP1_PAD_DRIVE_12MA		0x3
-
-enum {
-	RP1_PUD_OFF			= 0,
-	RP1_PUD_DOWN			= 1,
-	RP1_PUD_UP			= 2,
-};
-
-enum {
-	RP1_DIR_OUTPUT			= 0,
-	RP1_DIR_INPUT			= 1,
-};
-
-enum {
-	RP1_OUTOVER_PERI		= 0,
-	RP1_OUTOVER_INVPERI		= 1,
-	RP1_OUTOVER_LOW			= 2,
-	RP1_OUTOVER_HIGH		= 3,
-};
-
-enum {
-	RP1_OEOVER_PERI			= 0,
-	RP1_OEOVER_INVPERI		= 1,
-	RP1_OEOVER_DISABLE		= 2,
-	RP1_OEOVER_ENABLE		= 3,
-};
+#define RP1_DIR_OUTPUT			0
+#define RP1_DIR_INPUT			1
 
-enum {
-	RP1_INOVER_PERI			= 0,
-	RP1_INOVER_INVPERI		= 1,
-	RP1_INOVER_LOW			= 2,
-	RP1_INOVER_HIGH			= 3,
-};
+#define RP1_OUTOVER_PERI		0
+#define RP1_OUTOVER_INVPERI		1
+#define RP1_OUTOVER_LOW			2
+#define RP1_OUTOVER_HIGH		3
+
+#define RP1_OEOVER_PERI			0
+#define RP1_OEOVER_INVPERI		1
+#define RP1_OEOVER_DISABLE		2
+#define RP1_OEOVER_ENABLE		3
+
+#define RP1_INOVER_PERI			0
+#define RP1_INOVER_INVPERI		1
+#define RP1_INOVER_LOW			2
+#define RP1_INOVER_HIGH			3
+
+#define RP1_RIO_OUT			0x00
+#define RP1_RIO_OE			0x04
+#define RP1_RIO_IN			0x08
+
+#define RP1_PAD_SLEWFAST_MASK		0x00000001
+#define RP1_PAD_SLEWFAST_LSB		0
+#define RP1_PAD_SCHMITT_MASK		0x00000002
+#define RP1_PAD_SCHMITT_LSB		1
+#define RP1_PAD_PULL_MASK		0x0000000c
+#define RP1_PAD_PULL_LSB		2
+#define RP1_PAD_DRIVE_MASK		0x00000030
+#define RP1_PAD_DRIVE_LSB		4
+#define RP1_PAD_IN_ENABLE_MASK		0x00000040
+#define RP1_PAD_IN_ENABLE_LSB		6
+#define RP1_PAD_OUT_DISABLE_MASK	0x00000080
+#define RP1_PAD_OUT_DISABLE_LSB		7
+
+#define RP1_PAD_DRIVE_2MA		0x00000000
+#define RP1_PAD_DRIVE_4MA		0x00000010
+#define RP1_PAD_DRIVE_8MA		0x00000020
+#define RP1_PAD_DRIVE_12MA		0x00000030
 
-enum {
-	RP1_GPIO_CTRL_IRQRESET_SET		= 0,
-	RP1_GPIO_CTRL_INT_CLR			= 1,
-	RP1_GPIO_CTRL_INT_SET			= 2,
-	RP1_GPIO_CTRL_OEOVER			= 3,
-	RP1_GPIO_CTRL_FUNCSEL			= 4,
-	RP1_GPIO_CTRL_OUTOVER			= 5,
-	RP1_GPIO_CTRL				= 6,
-};
-
-enum {
-	RP1_INTE_SET			= 0,
-	RP1_INTE_CLR			= 1,
-};
-
-enum {
-	RP1_RIO_OUT_SET			= 0,
-	RP1_RIO_OUT_CLR			= 1,
-	RP1_RIO_OE			= 2,
-	RP1_RIO_OE_SET			= 3,
-	RP1_RIO_OE_CLR			= 4,
-	RP1_RIO_IN			= 5,
-};
-
-enum {
-	RP1_PAD_SLEWFAST		= 0,
-	RP1_PAD_SCHMITT			= 1,
-	RP1_PAD_PULL			= 2,
-	RP1_PAD_DRIVE			= 3,
-	RP1_PAD_IN_ENABLE		= 4,
-	RP1_PAD_OUT_DISABLE		= 5,
-};
-
-static const struct reg_field rp1_gpio_fields[] = {
-	[RP1_GPIO_CTRL_IRQRESET_SET]	= REG_FIELD(0x2004, 28, 28),
-	[RP1_GPIO_CTRL_INT_CLR]		= REG_FIELD(0x3004, 20, 23),
-	[RP1_GPIO_CTRL_INT_SET]		= REG_FIELD(0x2004, 20, 23),
-	[RP1_GPIO_CTRL_OEOVER]		= REG_FIELD(0x0004, 14, 15),
-	[RP1_GPIO_CTRL_FUNCSEL]		= REG_FIELD(0x0004, 0, 4),
-	[RP1_GPIO_CTRL_OUTOVER]		= REG_FIELD(0x0004, 12, 13),
-	[RP1_GPIO_CTRL]			= REG_FIELD(0x0004, 0, 31),
-};
-
-static const struct reg_field rp1_inte_fields[] = {
-	[RP1_INTE_SET]			= REG_FIELD(0x2000, 0, 0),
-	[RP1_INTE_CLR]			= REG_FIELD(0x3000, 0, 0),
-};
-
-static const struct reg_field rp1_rio_fields[] = {
-	[RP1_RIO_OUT_SET]		= REG_FIELD(0x2000, 0, 0),
-	[RP1_RIO_OUT_CLR]		= REG_FIELD(0x3000, 0, 0),
-	[RP1_RIO_OE]			= REG_FIELD(0x0004, 0, 0),
-	[RP1_RIO_OE_SET]		= REG_FIELD(0x2004, 0, 0),
-	[RP1_RIO_OE_CLR]		= REG_FIELD(0x3004, 0, 0),
-	[RP1_RIO_IN]			= REG_FIELD(0x0008, 0, 0),
-};
-
-static const struct reg_field rp1_pad_fields[] = {
-	[RP1_PAD_SLEWFAST]		= REG_FIELD(0, 0, 0),
-	[RP1_PAD_SCHMITT]		= REG_FIELD(0, 1, 1),
-	[RP1_PAD_PULL]			= REG_FIELD(0, 2, 3),
-	[RP1_PAD_DRIVE]			= REG_FIELD(0, 4, 5),
-	[RP1_PAD_IN_ENABLE]		= REG_FIELD(0, 6, 6),
-	[RP1_PAD_OUT_DISABLE]		= REG_FIELD(0, 7, 7),
-};
+#define FLD_GET(r, f) (((r) & (f ## _MASK)) >> (f ## _LSB))
+#define FLD_SET(r, f, v) r = (((r) & ~(f ## _MASK)) | ((v) << (f ## _LSB)))
 
 #define FUNC(f) \
 	[func_##f] = #f
@@ -172,6 +175,31 @@ static const struct reg_field rp1_pad_fi
 		func_##f3, \
 	}
 
+struct rp1_iobank_desc {
+	int min_gpio;
+	int num_gpios;
+	int gpio_offset;
+	int inte_offset;
+	int ints_offset;
+	int rio_offset;
+	int pads_offset;
+};
+
+struct rp1_pin_info {
+	u8 num;
+	u8 bank;
+	u8 offset;
+	u8 fsel;
+	u8 irq_type;
+
+	void __iomem *gpio;
+	void __iomem *rio;
+	void __iomem *inte;
+	void __iomem *ints;
+	void __iomem *pad;
+	void __iomem *dummy;
+};
+
 enum funcs {
 	func_alt0,
 	func_alt1,
@@ -184,9 +212,12 @@ enum funcs {
 	func_alt8,
 	func_none,
 	func_aaud,
+	func_dcd0,
 	func_dpi,
 	func_dsi0_te_ext,
 	func_dsi1_te_ext,
+	func_dsr0,
+	func_dtr0,
 	func_gpclk0,
 	func_gpclk1,
 	func_gpclk2,
@@ -210,6 +241,7 @@ enum funcs {
 	func_proc_rio,
 	func_pwm0,
 	func_pwm1,
+	func_ri0,
 	func_sd0,
 	func_sd1,
 	func_spi0,
@@ -240,34 +272,12 @@ struct rp1_pin_funcs {
 	u8 funcs[RP1_FSEL_COUNT];
 };
 
-struct rp1_iobank_desc {
-	int min_gpio;
-	int num_gpios;
-	int gpio_offset;
-	int inte_offset;
-	int ints_offset;
-	int rio_offset;
-	int pads_offset;
-};
-
-struct rp1_pin_info {
-	u8 num;
-	u8 bank;
-	u8 offset;
-	u8 fsel;
-	u8 irq_type;
-
-	struct regmap_field *gpio[ARRAY_SIZE(rp1_gpio_fields)];
-	struct regmap_field *rio[ARRAY_SIZE(rp1_rio_fields)];
-	struct regmap_field *inte[ARRAY_SIZE(rp1_inte_fields)];
-	struct regmap_field *pad[ARRAY_SIZE(rp1_pad_fields)];
-};
-
 struct rp1_pinctrl {
 	struct device *dev;
 	void __iomem *gpio_base;
 	void __iomem *rio_base;
 	void __iomem *pads_base;
+	void __iomem *dummy_base;
 	int irq[RP1_NUM_BANKS];
 	struct rp1_pin_info pins[RP1_NUM_GPIOS];
 
@@ -278,6 +288,13 @@ struct rp1_pinctrl {
 	raw_spinlock_t irq_lock[RP1_NUM_BANKS];
 };
 
+const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = {
+	/*         gpio   inte    ints     rio    pads */
+	{  0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 },
+	{ 28,  6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 },
+	{ 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 },
+};
+
 /* pins are just named GPIO0..GPIO53 */
 #define RP1_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
 static struct pinctrl_pin_desc rp1_gpio_pins[] = {
@@ -337,227 +354,128 @@ static struct pinctrl_pin_desc rp1_gpio_
 	RP1_GPIO_PIN(53),
 };
 
-#define PIN_ARRAY(...) \
-	(const unsigned int []) {__VA_ARGS__}
-#define PIN_ARRAY_SIZE(...) \
-	(sizeof((unsigned int[]) {__VA_ARGS__}) / sizeof(unsigned int))
-#define RP1_GROUP(name, ...) \
-	PINCTRL_PINGROUP(#name, PIN_ARRAY(__VA_ARGS__), \
-			 PIN_ARRAY_SIZE(__VA_ARGS__))
-
-static const struct pingroup rp1_gpio_groups[] = {
-	RP1_GROUP(uart0, 14, 15),
-	RP1_GROUP(uart0_ctrl, 4, 5, 6, 7, 16, 17),
-	RP1_GROUP(uart1, 0, 1),
-	RP1_GROUP(uart1_ctrl, 2, 3),
-	RP1_GROUP(uart2, 4, 5),
-	RP1_GROUP(uart2_ctrl, 6, 7),
-	RP1_GROUP(uart3, 8, 9),
-	RP1_GROUP(uart3_ctrl, 10, 11),
-	RP1_GROUP(uart4, 12, 13),
-	RP1_GROUP(uart4_ctrl, 14, 15),
-	RP1_GROUP(uart5_0, 30, 31),
-	RP1_GROUP(uart5_0_ctrl, 32, 33),
-	RP1_GROUP(uart5_1, 36, 37),
-	RP1_GROUP(uart5_1_ctrl, 38, 39),
-	RP1_GROUP(uart5_2, 40, 41),
-	RP1_GROUP(uart5_2_ctrl, 42, 43),
-	RP1_GROUP(uart5_3, 48, 49),
-	RP1_GROUP(sd0, 22, 23, 24, 25, 26, 27),
-	RP1_GROUP(sd1, 28, 29, 30, 31, 32, 33),
-	RP1_GROUP(i2s0, 18, 19, 20, 21),
-	RP1_GROUP(i2s0_dual, 18, 19, 20, 21, 22, 23),
-	RP1_GROUP(i2s0_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27),
-	RP1_GROUP(i2s1, 18, 19, 20, 21),
-	RP1_GROUP(i2s1_dual, 18, 19, 20, 21, 22, 23),
-	RP1_GROUP(i2s1_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27),
-	RP1_GROUP(i2s2_0, 28, 29, 30, 31),
-	RP1_GROUP(i2s2_0_dual, 28, 29, 30, 31, 32, 33),
-	RP1_GROUP(i2s2_1, 42, 43, 44, 45),
-	RP1_GROUP(i2s2_1_dual, 42, 43, 44, 45, 46, 47),
-	RP1_GROUP(i2c4_0, 28, 29),
-	RP1_GROUP(i2c4_1, 34, 35),
-	RP1_GROUP(i2c4_2, 40, 41),
-	RP1_GROUP(i2c4_3, 46, 47),
-	RP1_GROUP(i2c6_0, 38, 39),
-	RP1_GROUP(i2c6_1, 51, 52),
-	RP1_GROUP(i2c5_0, 30, 31),
-	RP1_GROUP(i2c5_1, 36, 37),
-	RP1_GROUP(i2c5_2, 44, 45),
-	RP1_GROUP(i2c5_3, 49, 50),
-	RP1_GROUP(i2c0_0, 0, 1),
-	RP1_GROUP(i2c0_1, 8, 9),
-	RP1_GROUP(i2c1_0, 2, 3),
-	RP1_GROUP(i2c1_1, 10, 11),
-	RP1_GROUP(i2c2_0, 4, 5),
-	RP1_GROUP(i2c2_1, 12, 13),
-	RP1_GROUP(i2c3_0, 6, 7),
-	RP1_GROUP(i2c3_1, 14, 15),
-	RP1_GROUP(i2c3_2, 22, 23),
-	RP1_GROUP(dpi_16bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-		  11, 12, 13, 14, 15, 16, 17, 18, 19),
-	RP1_GROUP(dpi_16bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8,
-		  12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24),
-	RP1_GROUP(dpi_16bit_pad666, 0, 1, 2, 3, 5, 6, 7, 8, 9,
-		  12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25),
-	RP1_GROUP(dpi_18bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-		  11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21),
-	RP1_GROUP(dpi_18bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8,
-		  9, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24,
-		  25),
-	RP1_GROUP(dpi_24bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-		  11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-		  22, 23, 24, 25, 26, 27),
-	RP1_GROUP(spi0, 9, 10, 11),
-	RP1_GROUP(spi0_quad, 0, 1, 9, 10, 11),
-	RP1_GROUP(spi1, 19, 20, 21),
-	RP1_GROUP(spi2, 1, 2, 3),
-	RP1_GROUP(spi3, 5, 6, 7),
-	RP1_GROUP(spi4, 9, 10, 11),
-	RP1_GROUP(spi5, 13, 14, 15),
-	RP1_GROUP(spi6_0, 28, 29, 30),
-	RP1_GROUP(spi6_1, 40, 41, 42),
-	RP1_GROUP(spi7_0, 46, 47, 48),
-	RP1_GROUP(spi7_1, 49, 50, 51),
-	RP1_GROUP(spi8_0, 37, 38, 39),
-	RP1_GROUP(spi8_1, 49, 50, 51),
-	RP1_GROUP(aaud_0, 12, 13),
-	RP1_GROUP(aaud_1, 38, 39),
-	RP1_GROUP(aaud_2, 40, 41),
-	RP1_GROUP(aaud_3, 49, 50),
-	RP1_GROUP(aaud_4, 51, 52),
-	RP1_GROUP(vbus0_0, 28, 29),
-	RP1_GROUP(vbus0_1, 34, 35),
-	RP1_GROUP(vbus1, 42, 43),
-	RP1_GROUP(vbus2, 50, 51),
-	RP1_GROUP(vbus3, 52, 53),
-	RP1_GROUP(mic_0, 25, 26, 27),
-	RP1_GROUP(mic_1, 34, 35, 36),
-	RP1_GROUP(mic_2, 37, 38, 39),
-	RP1_GROUP(mic_3, 46, 47, 48),
-	RP1_GROUP(ir, 2, 3),
-};
-
-#define GRP_ARRAY(...) \
-	(const char * []) {__VA_ARGS__}
-#define GRP_ARRAY_SIZE(...) \
-	(sizeof((char *[]) {__VA_ARGS__}) / sizeof(char *))
-#define RP1_FNC(f, ...) \
-	[func_##f] = PINCTRL_PINFUNCTION(#f, GRP_ARRAY(__VA_ARGS__), \
-					 GRP_ARRAY_SIZE(__VA_ARGS__))
-#define RP1_NULL_FNC(f) \
-	[func_##f] = PINCTRL_PINFUNCTION(#f, NULL, 0)
-#define RP1_ALL_LEGACY_PINS \
-		"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", \
-		"gpio5", "gpio6", "gpio7", "gpio8", "gpio9", \
-		"gpio10", "gpio11", "gpio12", "gpio13", "gpio14", \
-		"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", \
-		"gpio20", "gpio21", "gpio22", "gpio32", "gpio24", \
-		"gpio25", "gpio26", "gpio27"
-#define RP1_ALL_PINS RP1_ALL_LEGACY_PINS, \
-		"gpio28", "gpio29", "gpio30", "gpio31", "gpio32", \
-		"gpio33", "gpio34", "gpio35", "gpio36", "gpio37", \
-		"gpio38", "gpio39", "gpio40", "gpio41", "gpio42", \
-		"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", \
-		"gpio48", "gpio49", "gpio50", "gpio51", "gpio52", \
-		"gpio53"
-
-static const struct pinfunction rp1_func_names[] = {
-	RP1_NULL_FNC(alt0),
-	RP1_NULL_FNC(alt1),
-	RP1_NULL_FNC(alt2),
-	RP1_NULL_FNC(alt3),
-	RP1_NULL_FNC(alt4),
-	RP1_FNC(gpio, RP1_ALL_PINS),
-	RP1_NULL_FNC(alt6),
-	RP1_NULL_FNC(alt7),
-	RP1_NULL_FNC(alt8),
-	RP1_NULL_FNC(none),
-	RP1_FNC(aaud, "aaud_0", "aaud_1", "aaud_2", "aaud_3", "aaud_4",
-		"gpio12", "gpio13", "gpio38", "gpio39", "gpio40", "gpio41",
-		"gpio49", "gpio50", "gpio51", "gpio52"),
-	RP1_FNC(dpi, "dpi_16bit", "dpi_16bit_cpadhi",
-		"dpi_16bit_pad666", "dpi_18bit, dpi_18bit_cpadhi",
-		"dpi_24bit", RP1_ALL_LEGACY_PINS),
-	RP1_FNC(dsi0_te_ext, "gpio16", "gpio38", "gpio46"),
-	RP1_FNC(dsi1_te_ext, "gpio17", "gpio39", "gpio47"),
-	RP1_FNC(gpclk0, "gpio4", "gpio20"),
-	RP1_FNC(gpclk1, "gpio5", "gpio18", "gpio21"),
-	RP1_FNC(gpclk2, "gpio6"),
-	RP1_FNC(gpclk3, "gpio32", "gpio34", "gpio46"),
-	RP1_FNC(gpclk4, "gpio33", "gpio43"),
-	RP1_FNC(gpclk5, "gpio42", "gpio44", "gpio47"),
-	RP1_FNC(i2c0, "i2c0_0", "i2c0_1", "gpio0", "gpio1", "gpio8", "gpio9"),
-	RP1_FNC(i2c1, "i2c1_0", "i2c1_1", "gpio2", "gpio3", "gpio10", "gpio11"),
-	RP1_FNC(i2c2, "i2c2_0", "i2c2_1", "gpio4", "gpio5", "gpio12", "gpio13"),
-	RP1_FNC(i2c3, "i2c3_0", "i2c3_1", "i2c3_2", "gpio6", "gpio7", "gpio14",
-		"gpio15", "gpio22", "gpio23"),
-	RP1_FNC(i2c4, "i2c4_0", "i2c4_1", "i2c4_2", "i2c4_3", "gpio28",
-		"gpio29", "gpio34", "gpio35", "gpio40", "gpio41", "gpio46",
-		"gpio47"),
-	RP1_FNC(i2c5, "i2c5_0", "i2c5_1", "i2c5_2", "i2c5_3", "gpio30",
-		"gpio31", "gpio36", "gpio37", "gpio44", "gpio45", "gpio49",
-		"gpio50"),
-	RP1_FNC(i2c6, "i2c6_0", "i2c6_1", "gpio38", "gpio39", "gpio51",
-		"gpio52"),
-	RP1_FNC(i2s0, "i2s0", "i2s0_dual", "i2s0_quad", "gpio18", "gpio19",
-		"gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25",
-		"gpio26", "gpio27"),
-	RP1_FNC(i2s1, "i2s1", "i2s1_dual", "i2s1_quad", "gpio18", "gpio19",
-		"gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25",
-		"gpio26", "gpio27"),
-	RP1_FNC(i2s2, "i2s2_0", "i2s2_0_dual", "i2s2_1", "i2s2_1_dual",
-		"gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33",
-		"gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"),
-	RP1_FNC(ir, "gpio2", "gpio3"),
-	RP1_FNC(mic, "mic_0", "mic_1", "mic_2", "mic_3", "gpio25", "gpio26",
-		"gpio27", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38",
-		"gpio39", "gpio46", "gpio47", "gpio48"),
-	RP1_FNC(pcie_clkreq_n, "gpio36", "gpio37", "gpio48", "gpio53"),
-	RP1_FNC(pio, RP1_ALL_LEGACY_PINS),
-	RP1_FNC(proc_rio, RP1_ALL_PINS),
-	RP1_FNC(pwm0, "gpio12", "gpio13", "gpio14", "gpio15", "gpio18",
-		"gpio19"),
-	RP1_FNC(pwm1, "gpio34", "gpio35", "gpio40", "gpio41", "gpio44",
-		"gpio45", "gpio48"),
-	RP1_FNC(sd0, "sd0", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26",
-		"gpio27"),
-	RP1_FNC(sd1, "sd1", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-		"gpio33"),
-	RP1_FNC(spi0, "spi0", "spi0_quad", "gpio0", "gpio1", "gpio2", "gpio3",
-		"gpio7", "gpio8", "gpio9", "gpio10", "gpio11"),
-	RP1_FNC(spi1, "spi1", "gpio19", "gpio20", "gpio21", "gpio16", "gpio17",
-		"gpio18", "gpio27"),
-	RP1_FNC(spi2, "spi2", "gpio0", "gpio1", "gpio2", "gpio3", "gpio24"),
-	RP1_FNC(spi3, "spi3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio25"),
-	RP1_FNC(spi4, "spi4", "gpio8", "gpio9", "gpio10", "gpio11"),
-	RP1_FNC(spi5, "spi5", "gpio12", "gpio13", "gpio14", "gpio15", "gpio26"),
-	RP1_FNC(spi6, "spi6_0", "spi6_1", "gpio28", "gpio29", "gpio30",
-		"gpio31", "gpio32", "gpio33", "gpio40", "gpio41", "gpio42",
-		"gpio43", "gpio44", "gpio45"),
-	RP1_FNC(spi7, "spi7_0", "spi7_1", "gpio45", "gpio46", "gpio47",
-		"gpio48", "gpio49", "gpio50", "gpio51", "gpio53"),
-	RP1_FNC(spi8, "spi8_0", "spi8_1", "gpio35", "gpio36", "gpio37",
-		"gpio38", "gpio39", "gpio49", "gpio50", "gpio51", "gpio52",
-		"gpio53"),
-	RP1_FNC(uart0, "uart0", "uart0_ctrl", "gpio4", "gpio5", "gpio6",
-		"gpio7", "gpio14", "gpio15", "gpio16", "gpio17"),
-	RP1_FNC(uart1, "uart1", "uart1_ctrl", "gpio0", "gpio1", "gpio2",
-		"gpio3"),
-	RP1_FNC(uart2, "uart2", "uart2_ctrl", "gpio4", "gpio5", "gpio6",
-		"gpio7"),
-	RP1_FNC(uart3, "uart3", "uart3_ctrl", "gpio8", "gpio9", "gpio10",
-		"gpio11"),
-	RP1_FNC(uart4, "uart4", "uart4_ctrl", "gpio12", "gpio13", "gpio14",
-		"gpio15"),
-	RP1_FNC(uart5, "uart5_0", "uart5_0_ctrl", "uart5_1", "uart5_1_ctrl",
-		"uart5_2", "uart5_2_ctrl", "uart5_3"),
-	RP1_FNC(vbus0, "vbus0_0", "vbus0_1", "gpio28", "gpio29", "gpio34",
-		"gpio35"),
-	RP1_FNC(vbus1, "vbus1", "gpio42", "gpio43"),
-	RP1_FNC(vbus2, "vbus2", "gpio50", "gpio51"),
-	RP1_FNC(vbus3, "vbus3", "gpio52", "gpio53"),
-	RP1_NULL_FNC(invalid),	//[func_invalid] = "?"
+/* one pin per group */
+static const char * const rp1_gpio_groups[] = {
+	"gpio0",
+	"gpio1",
+	"gpio2",
+	"gpio3",
+	"gpio4",
+	"gpio5",
+	"gpio6",
+	"gpio7",
+	"gpio8",
+	"gpio9",
+	"gpio10",
+	"gpio11",
+	"gpio12",
+	"gpio13",
+	"gpio14",
+	"gpio15",
+	"gpio16",
+	"gpio17",
+	"gpio18",
+	"gpio19",
+	"gpio20",
+	"gpio21",
+	"gpio22",
+	"gpio23",
+	"gpio24",
+	"gpio25",
+	"gpio26",
+	"gpio27",
+	"gpio28",
+	"gpio29",
+	"gpio30",
+	"gpio31",
+	"gpio32",
+	"gpio33",
+	"gpio34",
+	"gpio35",
+	"gpio36",
+	"gpio37",
+	"gpio38",
+	"gpio39",
+	"gpio40",
+	"gpio41",
+	"gpio42",
+	"gpio43",
+	"gpio44",
+	"gpio45",
+	"gpio46",
+	"gpio47",
+	"gpio48",
+	"gpio49",
+	"gpio50",
+	"gpio51",
+	"gpio52",
+	"gpio53",
+};
+
+static const char * const rp1_func_names[] = {
+	FUNC(alt0),
+	FUNC(alt1),
+	FUNC(alt2),
+	FUNC(alt3),
+	FUNC(alt4),
+	FUNC(gpio),
+	FUNC(alt6),
+	FUNC(alt7),
+	FUNC(alt8),
+	FUNC(none),
+	FUNC(aaud),
+	FUNC(dcd0),
+	FUNC(dpi),
+	FUNC(dsi0_te_ext),
+	FUNC(dsi1_te_ext),
+	FUNC(dsr0),
+	FUNC(dtr0),
+	FUNC(gpclk0),
+	FUNC(gpclk1),
+	FUNC(gpclk2),
+	FUNC(gpclk3),
+	FUNC(gpclk4),
+	FUNC(gpclk5),
+	FUNC(i2c0),
+	FUNC(i2c1),
+	FUNC(i2c2),
+	FUNC(i2c3),
+	FUNC(i2c4),
+	FUNC(i2c5),
+	FUNC(i2c6),
+	FUNC(i2s0),
+	FUNC(i2s1),
+	FUNC(i2s2),
+	FUNC(ir),
+	FUNC(mic),
+	FUNC(pcie_clkreq_n),
+	FUNC(pio),
+	FUNC(proc_rio),
+	FUNC(pwm0),
+	FUNC(pwm1),
+	FUNC(ri0),
+	FUNC(sd0),
+	FUNC(sd1),
+	FUNC(spi0),
+	FUNC(spi1),
+	FUNC(spi2),
+	FUNC(spi3),
+	FUNC(spi4),
+	FUNC(spi5),
+	FUNC(spi6),
+	FUNC(spi7),
+	FUNC(spi8),
+	FUNC(uart0),
+	FUNC(uart1),
+	FUNC(uart2),
+	FUNC(uart3),
+	FUNC(uart4),
+	FUNC(uart5),
+	FUNC(vbus0),
+	FUNC(vbus1),
+	FUNC(vbus2),
+	FUNC(vbus3),
+	[func_invalid] = "?"
 };
 
 static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = {
@@ -565,10 +483,10 @@ static const struct rp1_pin_funcs rp1_gp
 	PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2),
 	PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
 	PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
-	PIN(4, gpclk0, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3),
-	PIN(5, gpclk1, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3),
-	PIN(6, gpclk2, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3),
-	PIN(7, spi0, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3),
+	PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3),
+	PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3),
+	PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3),
+	PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3),
 	PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
 	PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
 	PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4),
@@ -661,12 +579,41 @@ static bool persist_gpio_outputs = true;
 module_param(persist_gpio_outputs, bool, 0644);
 MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed");
 
-static const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = {
-	/*         gpio   inte    ints     rio    pads */
-	{  0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 },
-	{ 28,  6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 },
-	{ 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 },
-};
+static bool pace_pin_updates = true;
+module_param(pace_pin_updates, bool, 0644);
+MODULE_PARM_DESC(pace_pin_updates, "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled");
+
+static inline void rp1_pin_writel(u32 val, void __iomem *dummy, void __iomem *reg)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/*
+	 * Issuing 6 pipelined writes to the RC's Slot Control register will stall the
+	 * peripheral bus inside 2712 if the link is in L1. This acts as a lightweight
+	 * "fence" operation preventing back-to-back writes arriving at RP1 on a wake.
+	 */
+	if (dummy) {
+		writel_relaxed(0, dummy);
+		writel_relaxed(0, dummy);
+		writel_relaxed(0, dummy);
+		writel_relaxed(0, dummy);
+		writel_relaxed(0, dummy);
+		writel_relaxed(0, dummy);
+	}
+	writel_relaxed(val, reg);
+	local_irq_restore(flags);
+}
+
+static inline u32 rp1_pin_readl(const void __iomem *ioaddr)
+{
+	/*
+	 * Prior posted writes may not yet have been emitted by the CPU - do a store-flush
+	 * before reading GPIO state, as this will serialise writes versus the next issued read.
+	 */
+	__dma_wmb();
+	return readl(ioaddr);
+}
 
 static int rp1_pinconf_set(struct pinctrl_dev *pctldev,
 			   unsigned int offset, unsigned long *configs,
@@ -692,22 +639,33 @@ static struct rp1_pin_info *rp1_get_pin_
 	return NULL;
 }
 
+static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set)
+{
+	u32 padctrl = rp1_pin_readl(pin->pad);
+
+	padctrl &= ~clr;
+	padctrl |= set;
+
+	rp1_pin_writel(padctrl, pin->dummy, pin->pad);
+}
+
 static void rp1_input_enable(struct rp1_pin_info *pin, int value)
 {
-	regmap_field_write(pin->pad[RP1_PAD_IN_ENABLE], !!value);
+	rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK,
+		       value ? RP1_PAD_IN_ENABLE_MASK : 0);
 }
 
 static void rp1_output_enable(struct rp1_pin_info *pin, int value)
 {
-	regmap_field_write(pin->pad[RP1_PAD_OUT_DISABLE], !value);
+	rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK,
+		       value ? 0 : RP1_PAD_OUT_DISABLE_MASK);
 }
 
 static u32 rp1_get_fsel(struct rp1_pin_info *pin)
 {
-	u32 oeover, fsel;
-
-	regmap_field_read(pin->gpio[RP1_GPIO_CTRL_OEOVER], &oeover);
-	regmap_field_read(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], &fsel);
+	u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
+	u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER);
+	u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL);
 
 	if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT)
 		fsel = RP1_FSEL_NONE;
@@ -717,6 +675,8 @@ static u32 rp1_get_fsel(struct rp1_pin_i
 
 static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
 {
+	u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
+
 	if (fsel >= RP1_FSEL_COUNT)
 		fsel = RP1_FSEL_NONE_HW;
 
@@ -724,62 +684,52 @@ static void rp1_set_fsel(struct rp1_pin_
 	rp1_output_enable(pin, 1);
 
 	if (fsel == RP1_FSEL_NONE) {
-		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_DISABLE);
+		FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_DISABLE);
 	} else {
-		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OUTOVER], RP1_OUTOVER_PERI);
-		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_PERI);
+		FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI);
+		FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI);
 	}
-
-	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], fsel);
+	FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel);
+	rp1_pin_writel(ctrl, pin->dummy, pin->gpio + RP1_GPIO_CTRL);
 }
 
 static int rp1_get_dir(struct rp1_pin_info *pin)
 {
-	unsigned int val;
-
-	regmap_field_read(pin->rio[RP1_RIO_OE], &val);
-
-	return !val ? RP1_DIR_INPUT : RP1_DIR_OUTPUT;
+	return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ?
+		RP1_DIR_INPUT : RP1_DIR_OUTPUT;
 }
 
 static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input)
 {
-	int reg = is_input ? RP1_RIO_OE_CLR : RP1_RIO_OE_SET;
+	int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET;
 
-	regmap_field_write(pin->rio[reg], 1);
+	rp1_pin_writel(1 << pin->offset, pin->dummy, pin->rio + RP1_RIO_OE + offset);
 }
 
 static int rp1_get_value(struct rp1_pin_info *pin)
 {
-	unsigned int val;
-
-	regmap_field_read(pin->rio[RP1_RIO_IN], &val);
-
-	return !!val;
+	return !!(rp1_pin_readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset));
 }
 
 static void rp1_set_value(struct rp1_pin_info *pin, int value)
 {
 	/* Assume the pin is already an output */
-	int reg = value ? RP1_RIO_OUT_SET : RP1_RIO_OUT_CLR;
-
-	regmap_field_write(pin->rio[reg], 1);
+	rp1_pin_writel(1 << pin->offset, pin->dummy,
+		       pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
 }
 
-static int rp1_gpio_get(struct gpio_chip *chip, unsigned int offset)
+static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
 	int ret;
 
 	if (!pin)
 		return -EINVAL;
-
 	ret = rp1_get_value(pin);
-
 	return ret;
 }
 
-static int rp1_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+static int rp1_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
 
@@ -796,17 +746,15 @@ static int rp1_gpio_get_direction(struct
 
 	if (!pin)
 		return -EINVAL;
-
 	fsel = rp1_get_fsel(pin);
 	if (fsel != RP1_FSEL_GPIO)
 		return -EINVAL;
-
 	return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ?
 		GPIO_LINE_DIRECTION_OUT :
 		GPIO_LINE_DIRECTION_IN;
 }
 
-static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
 
@@ -814,11 +762,10 @@ static int rp1_gpio_direction_input(stru
 		return -EINVAL;
 	rp1_set_dir(pin, RP1_DIR_INPUT);
 	rp1_set_fsel(pin, RP1_FSEL_GPIO);
-
 	return 0;
 }
 
-static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
+static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 				     int value)
 {
 	struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
@@ -828,18 +775,17 @@ static int rp1_gpio_direction_output(str
 	rp1_set_value(pin, value);
 	rp1_set_dir(pin, RP1_DIR_OUTPUT);
 	rp1_set_fsel(pin, RP1_FSEL_GPIO);
-
 	return 0;
 }
 
-static int rp1_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset,
 			       unsigned long config)
 {
-	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+	struct rp1_pinctrl *pc = gpiochip_get_data(gc);
 	unsigned long configs[] = { config };
 
 	return rp1_pinconf_set(pc->pctl_dev, offset, configs,
-			       ARRAY_SIZE(configs));
+			      ARRAY_SIZE(configs));
 }
 
 static const struct gpio_chip rp1_gpio_chip = {
@@ -861,12 +807,12 @@ static const struct gpio_chip rp1_gpio_c
 static void rp1_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
-	struct irq_chip *host_chip = irq_desc_get_chip(desc);
 	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
 	const struct rp1_iobank_desc *bank;
 	int irq = irq_desc_get_irq(desc);
 	unsigned long ints;
-	int bit_pos;
+	int b;
 
 	if (pc->irq[0] == irq)
 		bank = &rp1_iobanks[0];
@@ -878,12 +824,13 @@ static void rp1_gpio_irq_handler(struct
 	chained_irq_enter(host_chip, desc);
 
 	ints = readl(pc->gpio_base + bank->ints_offset);
-	for_each_set_bit(bit_pos, &ints, 32) {
-		struct rp1_pin_info *pin = rp1_get_pin(chip, bit_pos);
+	for_each_set_bit(b, &ints, 32) {
+		struct rp1_pin_info *pin = rp1_get_pin(chip, bank->min_gpio + b);
 
-		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+		writel(RP1_GPIO_CTRL_IRQRESET,
+		       pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
 		generic_handle_irq(irq_find_mapping(pc->gpio_chip.irq.domain,
-						    bank->gpio_offset + bit_pos));
+						     bank->min_gpio + b));
 	}
 
 	chained_irq_exit(host_chip, desc);
@@ -891,18 +838,18 @@ static void rp1_gpio_irq_handler(struct
 
 static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable)
 {
-	int reg = enable ? RP1_INTE_SET : RP1_INTE_CLR;
-
-	regmap_field_write(pin->inte[reg], 1);
+	writel(1 << pin->offset,
+	       pin->inte + (enable ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
 	if (!enable)
 		/* Clear any latched events */
-		regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+		writel(RP1_GPIO_CTRL_IRQRESET,
+		       pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
 }
 
 static void rp1_gpio_irq_enable(struct irq_data *data)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int gpio = irqd_to_hwirq(data);
+	unsigned gpio = irqd_to_hwirq(data);
 	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
 
 	rp1_gpio_irq_config(pin, true);
@@ -911,7 +858,7 @@ static void rp1_gpio_irq_enable(struct i
 static void rp1_gpio_irq_disable(struct irq_data *data)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int gpio = irqd_to_hwirq(data);
+	unsigned gpio = irqd_to_hwirq(data);
 	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
 
 	rp1_gpio_irq_config(pin, false);
@@ -945,11 +892,15 @@ static int rp1_irq_set_type(struct rp1_p
 		return -EINVAL;
 	}
 
-	/* Clear them all */
-	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_CLR], RP1_INT_MASK);
-
-	/* Set those that are needed */
-	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_SET], irq_flags);
+	/* Clear the event enables */
+	writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW,
+	       pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL);
+	/* Clear any latched events */
+	writel(RP1_GPIO_CTRL_IRQRESET,
+		pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
+	/* Enable the events that are needed */
+	writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW,
+	       pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
 	pin->irq_type = type;
 
 	return 0;
@@ -958,9 +909,9 @@ static int rp1_irq_set_type(struct rp1_p
 static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int gpio = irqd_to_hwirq(data);
-	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
 	struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+	unsigned gpio = irqd_to_hwirq(data);
+	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
 	int bank = pin->bank;
 	unsigned long flags;
 	int ret;
@@ -983,11 +934,11 @@ static int rp1_gpio_irq_set_type(struct
 static void rp1_gpio_irq_ack(struct irq_data *data)
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-	unsigned int gpio = irqd_to_hwirq(data);
+	unsigned gpio = irqd_to_hwirq(data);
 	struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
 
 	/* Clear any latched events */
-	regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+	writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
 }
 
 static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force)
@@ -1023,26 +974,20 @@ static struct irq_chip rp1_gpio_irq_chip
 	.irq_unmask = rp1_gpio_irq_enable,
 	.irq_set_affinity = rp1_gpio_irq_set_affinity,
 	.flags = IRQCHIP_IMMUTABLE,
-	GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static int rp1_pctl_get_groups_count(struct pinctrl_dev *pctldev)
 {
-	return ARRAY_SIZE(rp1_gpio_groups) + ARRAY_SIZE(rp1_gpio_pins);
+	return ARRAY_SIZE(rp1_gpio_groups);
 }
 
 static const char *rp1_pctl_get_group_name(struct pinctrl_dev *pctldev,
-					   unsigned int selector)
+					   unsigned selector)
 {
-	unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups);
-
-	if (selector < ngroups)
-		return rp1_gpio_groups[selector].name;
-
-	return rp1_gpio_pins[selector - ngroups].name;
+	return rp1_gpio_groups[selector];
 }
 
-static enum funcs rp1_get_fsel_func(unsigned int pin, unsigned int fsel)
+static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel)
 {
 	if (pin < RP1_NUM_GPIOS) {
 		if (fsel < RP1_FSEL_COUNT)
@@ -1054,26 +999,19 @@ static enum funcs rp1_get_fsel_func(unsi
 }
 
 static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev,
-				   unsigned int selector,
-				   const unsigned int **pins,
-				   unsigned int *num_pins)
-{
-	unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups);
-
-	if (selector < ngroups) {
-		*pins = rp1_gpio_groups[selector].pins;
-		*num_pins = rp1_gpio_groups[selector].npins;
-	} else {
-		*pins = &rp1_gpio_pins[selector - ngroups].number;
-		*num_pins = 1;
-	}
+				   unsigned selector,
+				   const unsigned **pins,
+				   unsigned *num_pins)
+{
+	*pins = &rp1_gpio_pins[selector].number;
+	*num_pins = 1;
 
 	return 0;
 }
 
 static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 				  struct seq_file *s,
-				  unsigned int offset)
+				  unsigned offset)
 {
 	struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
 	struct gpio_chip *chip = &pc->gpio_chip;
@@ -1084,13 +1022,13 @@ static void rp1_pctl_pin_dbg_show(struct
 	int irq = irq_find_mapping(chip->irq.domain, offset);
 
 	seq_printf(s, "function %s (%s) in %s; irq %d (%s)",
-		   rp1_func_names[fsel].name, rp1_func_names[func].name,
+		   rp1_func_names[fsel], rp1_func_names[func],
 		   value ? "hi" : "lo",
 		   irq, irq_type_names[pin->irq_type]);
 }
 
 static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev,
-				 struct pinctrl_map *maps, unsigned int num_maps)
+				 struct pinctrl_map *maps, unsigned num_maps)
 {
 	int i;
 
@@ -1124,11 +1062,14 @@ static int rp1_pctl_legacy_map_func(stru
 		return -EINVAL;
 	}
 
+	if (func == func_invalid) {
+		dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n",
+			np, fnum, pin);
+	}
+
 	map->type = PIN_MAP_TYPE_MUX_GROUP;
-	map->data.mux.group = rp1_pctl_get_group_name(pc->pctl_dev,
-						      ARRAY_SIZE(rp1_gpio_groups)
-						      + pin);
-	map->data.mux.function = rp1_func_names[func].name;
+	map->data.mux.group = rp1_gpio_groups[pin];
+	map->data.mux.function = rp1_func_names[func];
 	(*num_maps)++;
 
 	return 0;
@@ -1254,7 +1195,7 @@ static int rp1_pctl_dt_node_to_map(struc
 		} else if (function) {
 			err = pinctrl_utils_add_map_mux(pctldev, &maps,
 							&reserved_maps, num_maps,
-							rp1_gpio_groups[pin].name,
+							rp1_gpio_groups[pin],
 							function);
 		}
 
@@ -1272,7 +1213,7 @@ static int rp1_pctl_dt_node_to_map(struc
 		} else if (num_configs) {
 			err = pinctrl_utils_add_map_configs(pctldev, &maps,
 							    &reserved_maps, num_maps,
-							    rp1_gpio_groups[pin].name,
+							    rp1_gpio_groups[pin],
 							    configs, num_configs,
 							    PIN_MAP_TYPE_CONFIGS_PIN);
 		}
@@ -1299,7 +1240,7 @@ static const struct pinctrl_ops rp1_pctl
 	.dt_free_map = rp1_pctl_dt_free_map,
 };
 
-static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned int offset)
+static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
 {
 	struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
 	u32 fsel = rp1_get_fsel(pin);
@@ -1320,66 +1261,61 @@ static int rp1_pmx_get_functions_count(s
 }
 
 static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev,
-					     unsigned int selector)
+					     unsigned selector)
 {
-	return (selector < func_count) ? rp1_func_names[selector].name : NULL;
+	return (selector < func_count) ? rp1_func_names[selector] : NULL;
 }
 
 static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev,
-				       unsigned int selector,
+				       unsigned selector,
 				       const char * const **groups,
 				       unsigned * const num_groups)
 {
-	*groups = rp1_func_names[selector].groups;
-	*num_groups = rp1_func_names[selector].ngroups;
+	/* every pin can do every function */
+	*groups = rp1_gpio_groups;
+	*num_groups = ARRAY_SIZE(rp1_gpio_groups);
 
 	return 0;
 }
 
-static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned int func_selector,
-		       unsigned int group_selector)
+static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector,
+		       unsigned group_selector)
 {
-	struct rp1_pin_info *pin;
-	const unsigned int *pins;
+	struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, group_selector);
 	const u8 *pin_funcs;
-	unsigned int num_pins;
-	int offset, fsel;
+	int fsel;
 
-	rp1_pctl_get_group_pins(pctldev, group_selector, &pins, &num_pins);
+	/* func_selector is an enum funcs, so needs translation */
 
-	for (offset = 0; offset < num_pins; ++offset) {
-		pin = rp1_get_pin_pctl(pctldev, pins[offset]);
-		/* func_selector is an enum funcs, so needs translation */
-		if (func_selector >= RP1_FSEL_COUNT) {
-			/* Convert to an fsel number */
-			pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs;
-			for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) {
-				if (pin_funcs[fsel] == func_selector)
-					break;
-			}
-		} else {
-			fsel = (int)func_selector;
+	if (func_selector >= RP1_FSEL_COUNT) {
+		/* Convert to an fsel number */
+		pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs;
+		for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) {
+			if (pin_funcs[fsel] == func_selector)
+				break;
 		}
+	} else {
+		fsel = (int)func_selector;
+	}
 
-		if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE)
-			return -EINVAL;
+	if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE)
+		return -EINVAL;
 
-		rp1_set_fsel(pin, fsel);
-	}
+	rp1_set_fsel(pin, fsel);
 
 	return 0;
 }
 
 static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
 				      struct pinctrl_gpio_range *range,
-				      unsigned int offset)
+				      unsigned offset)
 {
 	(void)rp1_pmx_free(pctldev, offset);
 }
 
 static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
 				      struct pinctrl_gpio_range *range,
-				      unsigned int offset,
+				      unsigned offset,
 				      bool input)
 {
 	struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
@@ -1402,9 +1338,15 @@ static const struct pinmux_ops rp1_pmx_o
 
 static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
 {
-	regmap_field_write(pin->pad[RP1_PAD_PULL], arg & 0x3);
+	u32 padctrl = rp1_pin_readl(pin->pad);
+
+	FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3);
+
+	writel(padctrl, pin->pad);
 }
 
+/* Generic pinconf methods */
+
 static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset,
 			   unsigned long *configs, unsigned int num_configs)
 {
@@ -1447,11 +1389,13 @@ static int rp1_pinconf_set(struct pinctr
 			break;
 
 		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
-			regmap_field_write(pin->pad[RP1_PAD_SCHMITT], !!arg);
+			rp1_pad_update(pin, RP1_PAD_SCHMITT_MASK,
+				       arg ? RP1_PAD_SCHMITT_MASK : 0);
 			break;
 
 		case PIN_CONFIG_SLEW_RATE:
-			regmap_field_write(pin->pad[RP1_PAD_SLEWFAST], !!arg);
+			rp1_pad_update(pin, RP1_PAD_SLEWFAST_MASK,
+				       arg ? RP1_PAD_SLEWFAST_MASK : 0);
 			break;
 
 		case PIN_CONFIG_DRIVE_STRENGTH:
@@ -1471,7 +1415,7 @@ static int rp1_pinconf_set(struct pinctr
 			default:
 				return -ENOTSUPP;
 			}
-			regmap_field_write(pin->pad[RP1_PAD_DRIVE], arg);
+			rp1_pad_update(pin, RP1_PAD_DRIVE_MASK, arg);
 			break;
 
 		default:
@@ -1483,7 +1427,7 @@ static int rp1_pinconf_set(struct pinctr
 	return 0;
 }
 
-static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset,
+static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset,
 			   unsigned long *config)
 {
 	struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
@@ -1494,26 +1438,23 @@ static int rp1_pinconf_get(struct pinctr
 	if (!pin)
 		return -EINVAL;
 
+	padctrl = rp1_pin_readl(pin->pad);
+
 	switch (param) {
 	case PIN_CONFIG_INPUT_ENABLE:
-		regmap_field_read(pin->pad[RP1_PAD_IN_ENABLE], &padctrl);
-		arg = !!padctrl;
+		arg = !!(padctrl & RP1_PAD_IN_ENABLE_MASK);
 		break;
 	case PIN_CONFIG_OUTPUT_ENABLE:
-		regmap_field_read(pin->pad[RP1_PAD_OUT_DISABLE], &padctrl);
-		arg = !padctrl;
+		arg = !(padctrl & RP1_PAD_OUT_DISABLE_MASK);
 		break;
 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
-		regmap_field_read(pin->pad[RP1_PAD_SCHMITT], &padctrl);
-		arg = !!padctrl;
+		arg = !!(padctrl & RP1_PAD_SCHMITT_MASK);
 		break;
 	case PIN_CONFIG_SLEW_RATE:
-		regmap_field_read(pin->pad[RP1_PAD_SLEWFAST], &padctrl);
-		arg = !!padctrl;
+		arg = !!(padctrl & RP1_PAD_SLEWFAST_MASK);
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		regmap_field_read(pin->pad[RP1_PAD_DRIVE], &padctrl);
-		switch (padctrl) {
+		switch (padctrl & RP1_PAD_DRIVE_MASK) {
 		case RP1_PAD_DRIVE_2MA:
 			arg = 2;
 			break;
@@ -1529,17 +1470,14 @@ static int rp1_pinconf_get(struct pinctr
 		}
 		break;
 	case PIN_CONFIG_BIAS_DISABLE:
-		regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
-		arg = ((padctrl == RP1_PUD_OFF));
+		arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_OFF << RP1_PAD_PULL_LSB));
 		break;
 	case PIN_CONFIG_BIAS_PULL_DOWN:
-		regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
-		arg = ((padctrl == RP1_PUD_DOWN));
+		arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_DOWN << RP1_PAD_PULL_LSB));
 		break;
 
 	case PIN_CONFIG_BIAS_PULL_UP:
-		regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
-		arg = ((padctrl == RP1_PUD_UP));
+		arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_UP << RP1_PAD_PULL_LSB));
 		break;
 	default:
 		return -ENOTSUPP;
@@ -1550,51 +1488,10 @@ static int rp1_pinconf_get(struct pinctr
 	return 0;
 }
 
-static int rp1_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int selector,
-				 unsigned long *config)
-{
-	const unsigned int *pins;
-	unsigned int npins;
-	int ret;
-
-	ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins);
-	if (ret < 0)
-		return ret;
-
-	if (!npins)
-		return -ENODEV;
-
-	ret = rp1_pinconf_get(pctldev, pins[0], config);
-
-	return ret;
-}
-
-static int rp1_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int selector,
-				 unsigned long *configs, unsigned int num_configs)
-{
-	const unsigned int *pins;
-	unsigned int npins;
-	int ret, i;
-
-	ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < npins; i++) {
-		ret = rp1_pinconf_set(pctldev, pins[i], configs, num_configs);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
 static const struct pinconf_ops rp1_pinconf_ops = {
 	.is_generic = true,
 	.pin_config_get = rp1_pinconf_get,
 	.pin_config_set = rp1_pinconf_set,
-	.pin_config_group_get = rp1_pinconf_group_get,
-	.pin_config_group_set = rp1_pinconf_group_set,
 };
 
 static struct pinctrl_desc rp1_pinctrl_desc = {
@@ -1617,169 +1514,94 @@ static const struct of_device_id rp1_pin
 		.compatible = "raspberrypi,rp1-gpio",
 		.data = &rp1_pinconf_ops,
 	},
-	{},
+	{}
 };
-MODULE_DEVICE_TABLE(of, rp1_pinctrl_match);
-
-static struct rp1_pinctrl rp1_pinctrl_data = {};
 
-static const struct regmap_range rp1_gpio_reg_ranges[] = {
-	/* BANK 0 */
-	regmap_reg_range(0x2004, 0x20dc),
-	regmap_reg_range(0x3004, 0x30dc),
-	regmap_reg_range(0x0004, 0x00dc),
-	regmap_reg_range(0x0124, 0x0124),
-	regmap_reg_range(0x211c, 0x211c),
-	regmap_reg_range(0x311c, 0x311c),
-	/* BANK 1 */
-	regmap_reg_range(0x6004, 0x602c),
-	regmap_reg_range(0x7004, 0x702c),
-	regmap_reg_range(0x4004, 0x402c),
-	regmap_reg_range(0x4124, 0x4124),
-	regmap_reg_range(0x611c, 0x611c),
-	regmap_reg_range(0x711c, 0x711c),
-	/* BANK 2 */
-	regmap_reg_range(0xa004, 0xa09c),
-	regmap_reg_range(0xb004, 0xb09c),
-	regmap_reg_range(0x8004, 0x809c),
-	regmap_reg_range(0x8124, 0x8124),
-	regmap_reg_range(0xa11c, 0xa11c),
-	regmap_reg_range(0xb11c, 0xb11c),
-};
-
-static const struct regmap_range rp1_rio_reg_ranges[] = {
-	/* BANK 0 */
-	regmap_reg_range(0x2000, 0x2004),
-	regmap_reg_range(0x3000, 0x3004),
-	regmap_reg_range(0x0004, 0x0008),
-	/* BANK 1 */
-	regmap_reg_range(0x6000, 0x6004),
-	regmap_reg_range(0x7000, 0x7004),
-	regmap_reg_range(0x4004, 0x4008),
-	/* BANK 2 */
-	regmap_reg_range(0xa000, 0xa004),
-	regmap_reg_range(0xb000, 0xb004),
-	regmap_reg_range(0x8004, 0x8008),
-};
-
-static const struct regmap_range rp1_pads_reg_ranges[] = {
-	/* BANK 0 */
-	regmap_reg_range(0x0004, 0x0070),
-	/* BANK 1 */
-	regmap_reg_range(0x4004, 0x4018),
-	/* BANK 2 */
-	regmap_reg_range(0x8004, 0x8050),
-};
-
-static const struct regmap_access_table rp1_gpio_reg_table = {
-	.yes_ranges = rp1_gpio_reg_ranges,
-	.n_yes_ranges = ARRAY_SIZE(rp1_gpio_reg_ranges),
-};
-
-static const struct regmap_access_table rp1_rio_reg_table = {
-	.yes_ranges = rp1_rio_reg_ranges,
-	.n_yes_ranges = ARRAY_SIZE(rp1_rio_reg_ranges),
-};
-
-static const struct regmap_access_table rp1_pads_reg_table = {
-	.yes_ranges = rp1_pads_reg_ranges,
-	.n_yes_ranges = ARRAY_SIZE(rp1_pads_reg_ranges),
-};
-
-static const struct regmap_config rp1_pinctrl_gpio_regmap_cfg = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-	.rd_table = &rp1_gpio_reg_table,
-	.name = "rp1-gpio",
-	.max_register = 0xb11c,
-};
-
-static const struct regmap_config rp1_pinctrl_rio_regmap_cfg = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-	.rd_table = &rp1_rio_reg_table,
-	.name = "rp1-rio",
-	.max_register = 0xb004,
-};
-
-static const struct regmap_config rp1_pinctrl_pads_regmap_cfg = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-	.rd_table = &rp1_pads_reg_table,
-	.name = "rp1-pads",
-	.max_register = 0x8050,
-};
-
-static int rp1_gen_regfield(struct device *dev,
-			    const struct reg_field *array,
-			    size_t array_size,
-			    int reg_off,
-			    int pin_off,
-			    bool additive_offset,
-			    struct regmap *regmap,
-			    struct regmap_field *out[])
-{
-	struct reg_field regfield;
-	int k;
-
-	for (k = 0; k < array_size; k++) {
-		regfield = array[k];
-		regfield.reg = (additive_offset ? regfield.reg : 0) + reg_off;
-		if (pin_off >= 0) {
-			regfield.lsb = pin_off;
-			regfield.msb = regfield.lsb;
-		}
-		out[k] = devm_regmap_field_alloc(dev, regmap, regfield);
-
-		if (IS_ERR(out[k]))
-			return PTR_ERR(out[k]);
-	}
+static inline void __iomem *devm_auto_iomap(struct platform_device *pdev,
+					    unsigned int index)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 
-	return 0;
+	if (np)
+		return devm_of_iomap(dev, np, (int)index, NULL);
+	else
+		return devm_platform_ioremap_resource(pdev, index);
 }
 
 static int rp1_pinctrl_probe(struct platform_device *pdev)
 {
-	struct regmap *gpio_regmap, *rio_regmap, *pads_regmap;
-	struct rp1_pinctrl *pc = &rp1_pinctrl_data;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	struct device_node *rp1_node = NULL;
+	struct rp1_pinctrl *pc;
 	struct gpio_irq_chip *girq;
 	int err, i;
 
+	BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_pins) != RP1_NUM_GPIOS);
+	BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_groups) != RP1_NUM_GPIOS);
+
+	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, pc);
 	pc->dev = dev;
+
+	pc->gpio_base = devm_auto_iomap(pdev, 0);
+	if (IS_ERR(pc->gpio_base)) {
+		dev_err(dev, "could not get GPIO IO memory\n");
+		return PTR_ERR(pc->gpio_base);
+	}
+
+	pc->rio_base = devm_auto_iomap(pdev, 1);
+	if (IS_ERR(pc->rio_base)) {
+		dev_err(dev, "could not get RIO IO memory\n");
+		return PTR_ERR(pc->rio_base);
+	}
+
+	pc->pads_base = devm_auto_iomap(pdev, 2);
+	if (IS_ERR(pc->pads_base)) {
+		dev_err(dev, "could not get PADS IO memory\n");
+		return PTR_ERR(pc->pads_base);
+	}
+
 	pc->gpio_chip = rp1_gpio_chip;
 	pc->gpio_chip.parent = dev;
 
-	pc->gpio_base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(pc->gpio_base))
-		return dev_err_probe(dev, PTR_ERR(pc->gpio_base), "could not get GPIO IO memory\n");
-
-	pc->rio_base = devm_platform_ioremap_resource(pdev, 1);
-	if (IS_ERR(pc->rio_base))
-		return dev_err_probe(dev, PTR_ERR(pc->rio_base), "could not get RIO IO memory\n");
-
-	pc->pads_base = devm_platform_ioremap_resource(pdev, 2);
-	if (IS_ERR(pc->pads_base))
-		return dev_err_probe(dev, PTR_ERR(pc->pads_base), "could not get PADS IO memory\n");
-
-	gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base,
-					    &rp1_pinctrl_gpio_regmap_cfg);
-	if (IS_ERR(gpio_regmap))
-		return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n");
-
-	rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base,
-					   &rp1_pinctrl_rio_regmap_cfg);
-	if (IS_ERR(rio_regmap))
-		return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n");
-
-	pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base,
-					    &rp1_pinctrl_pads_regmap_cfg);
-	if (IS_ERR(pads_regmap))
-		return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n");
+	/*
+	 * Workaround for the vagaries of PCIe on BCM2712
+	 *
+	 * If the link to RP1 is in L1, then the BRCMSTB RC will buffer many
+	 * outbound writes - and generate write responses for them, despite the
+	 * fact that the link is not yet active. This has the effect of compressing
+	 * multiple writes to GPIOs together, destroying any pacing that an application
+	 * may require in the 1-10us range.
+	 *
+	 * The RC Slot Control configuration register is special. It emits a
+	 * MsgD for every write to it, will stall further writes until the message
+	 * goes out on the wire. This can be (ab)used to force CPU stalls when the
+	 * link is inactive, at the cost of a small amount of downstream bandwidth
+	 * and some 200ns of added latency for each write.
+	 *
+	 * Several back-to-back configuration writes are necessary to "fill the pipe",
+	 * otherwise the outbound MAC can consume a pending MMIO write and reorder
+	 * it with respect to the config writes - undoing the intent.
+	 *
+	 * of_iomap() is used directly here as the address overlaps with the RC driver's
+	 * usage.
+	 */
+	rp1_node = of_find_node_by_name(NULL, "rp1");
+	if (!rp1_node)
+		dev_err(&pdev->dev, "failed to find RP1 DT node\n");
+	else if (pace_pin_updates &&
+		 of_device_is_compatible(rp1_node->parent, "brcm,bcm2712-pcie")) {
+		pc->dummy_base = of_iomap(rp1_node->parent, 0);
+		if (IS_ERR(pc->dummy_base)) {
+			dev_warn(&pdev->dev, "could not map bcm2712 root complex registers\n");
+			pc->dummy_base = NULL;
+		}
+	}
 
 	for (i = 0; i < RP1_NUM_BANKS; i++) {
 		const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
@@ -1788,85 +1610,35 @@ static int rp1_pinctrl_probe(struct plat
 		for (j = 0; j < bank->num_gpios; j++) {
 			struct rp1_pin_info *pin =
 				&pc->pins[bank->min_gpio + j];
-			int reg_off;
 
 			pin->num = bank->min_gpio + j;
 			pin->bank = i;
 			pin->offset = j;
 
-			reg_off = bank->gpio_offset + pin->offset *
-				  sizeof(u32) * 2;
-			err = rp1_gen_regfield(dev,
-					       rp1_gpio_fields,
-					       ARRAY_SIZE(rp1_gpio_fields),
-					       reg_off,
-					       -1,
-					       true,
-					       gpio_regmap,
-					       pin->gpio);
-
-			if (err)
-				return dev_err_probe(dev, err,
-						     "Unable to allocate regmap for gpio\n");
-
-			reg_off = bank->inte_offset;
-			err = rp1_gen_regfield(dev,
-					       rp1_inte_fields,
-					       ARRAY_SIZE(rp1_inte_fields),
-					       reg_off,
-					       pin->offset,
-					       true,
-					       gpio_regmap,
-					       pin->inte);
-
-			if (err)
-				return dev_err_probe(dev, err,
-						     "Unable to allocate regmap for inte\n");
-
-			reg_off = bank->rio_offset;
-			err = rp1_gen_regfield(dev,
-					       rp1_rio_fields,
-					       ARRAY_SIZE(rp1_rio_fields),
-					       reg_off,
-					       pin->offset,
-					       true,
-					       rio_regmap,
-					       pin->rio);
-
-			if (err)
-				return dev_err_probe(dev, err,
-						     "Unable to allocate regmap for rio\n");
-
-			reg_off = bank->pads_offset + pin->offset * sizeof(u32);
-			err = rp1_gen_regfield(dev,
-					       rp1_pad_fields,
-					       ARRAY_SIZE(rp1_pad_fields),
-					       reg_off,
-					       -1,
-					       false,
-					       pads_regmap,
-					       pin->pad);
-
-			if (err)
-				return dev_err_probe(dev, err,
-						     "Unable to allocate regmap for pad\n");
+			pin->gpio = pc->gpio_base + bank->gpio_offset +
+				    j * sizeof(u32) * 2;
+			pin->inte = pc->gpio_base + bank->inte_offset;
+			pin->ints = pc->gpio_base + bank->ints_offset;
+			pin->rio  = pc->rio_base + bank->rio_offset;
+			pin->pad  = pc->pads_base + bank->pads_offset +
+				    j * sizeof(u32);
+			pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 : NULL;
 		}
 
 		raw_spin_lock_init(&pc->irq_lock[i]);
 	}
 
 	pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc);
-	if (IS_ERR(pc->pctl_dev))
-		return dev_err_probe(dev, PTR_ERR(pc->pctl_dev),
-				     "Could not register pin controller\n");
+	if (IS_ERR(pc->pctl_dev)) {
+		err = PTR_ERR(pc->pctl_dev);
+		goto out_iounmap;
+	}
 
 	girq = &pc->gpio_chip.irq;
 	girq->chip = &rp1_gpio_irq_chip;
 	girq->parent_handler = rp1_gpio_irq_handler;
 	girq->num_parents = RP1_NUM_BANKS;
 	girq->parents = pc->irq;
-	girq->default_type = IRQ_TYPE_NONE;
-	girq->handler = handle_level_irq;
 
 	/*
 	 * Use the same handler for all groups: this is necessary
@@ -1883,11 +1655,14 @@ static int rp1_pinctrl_probe(struct plat
 		}
 	}
 
-	platform_set_drvdata(pdev, pc);
+	girq->default_type = IRQ_TYPE_NONE;
+	girq->handler = handle_level_irq;
 
 	err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
-	if (err)
-		return dev_err_probe(dev, err, "could not add GPIO chip\n");
+	if (err) {
+		dev_err(dev, "could not add GPIO chip\n");
+		goto out_iounmap;
+	}
 
 	pc->gpio_range = rp1_pinctrl_gpio_range;
 	pc->gpio_range.base = pc->gpio_chip.base;
@@ -1895,10 +1670,24 @@ static int rp1_pinctrl_probe(struct plat
 	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
 
 	return 0;
+
+out_iounmap:
+	if (pc->dummy_base)
+		iounmap(pc->dummy_base);
+	return err;
+}
+
+static void rp1_pinctrl_remove(struct platform_device *pdev)
+{
+	struct rp1_pinctrl *pc = platform_get_drvdata(pdev);
+
+	if (pc->dummy_base)
+		iounmap(pc->dummy_base);
 }
 
 static struct platform_driver rp1_pinctrl_driver = {
 	.probe = rp1_pinctrl_probe,
+	.remove = rp1_pinctrl_remove,
 	.driver = {
 		.name = MODULE_NAME,
 		.of_match_table = rp1_pinctrl_match,
