[PATCH] realtek: replace RTL93xx GPIO patches

Sander Vanheule sander at svanheule.net
Fri Apr 15 02:02:15 PDT 2022


Patches to support the SoC's GPIO controller for RTL930x and RTL931x
devices have been accepted upstream. Replace the current preliminary
patch with the upstream ones, excluding devictree binding changes.

The updated patches add GPIO IRQ balancing support on RTL930x, but this
cannot be used until these devices also support SMP.

Signed-off-by: Sander Vanheule <sander at svanheule.net>
---
 ...-otto-Support-reversed-port-layouts.patch} |  86 +++-------
 ...ltek-otto-Support-per-cpu-interrupts.patch | 153 ++++++++++++++++++
 ...pio-realtek-otto-Add-RTL930x-support.patch |  29 ++++
 ...pio-realtek-otto-Add-RTL931x-support.patch |  30 ++++
 4 files changed, 234 insertions(+), 64 deletions(-)
 rename target/linux/realtek/patches-5.10/{320-gpio-add-support-for-RTL930X-and-RTL931X.patch => 021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch} (63%)
 create mode 100644 target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
 create mode 100644 target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch
 create mode 100644 target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch

diff --git a/target/linux/realtek/patches-5.10/320-gpio-add-support-for-RTL930X-and-RTL931X.patch b/target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch
similarity index 63%
rename from target/linux/realtek/patches-5.10/320-gpio-add-support-for-RTL930X-and-RTL931X.patch
rename to target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch
index bd4639433d02..8f3535143888 100644
--- a/target/linux/realtek/patches-5.10/320-gpio-add-support-for-RTL930X-and-RTL931X.patch
+++ b/target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch
@@ -1,10 +1,22 @@
+From 512c5be35223d9baa2629efa1084cf5210eaee80 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander at svanheule.net>
+Date: Sat, 9 Apr 2022 21:55:47 +0200
+Subject: [PATCH 2/6] gpio: realtek-otto: Support reversed port layouts
+
+The GPIO port layout on the RTL930x SoC series is reversed compared to
+the RTL838x and RTL839x SoC series. Add new port offset calculator
+functions to ensure the correct order is used when reading port IRQ
+data, and ensure bgpio uses the right byte ordering.
+
+Signed-off-by: Sander Vanheule <sander at svanheule.net>
+Signed-off-by: Bartosz Golaszewski <brgl at bgdev.pl>
+---
+ drivers/gpio/gpio-realtek-otto.c | 55 +++++++++++++++++++++++++++++---
+ 1 file changed, 51 insertions(+), 4 deletions(-)
+
 --- a/drivers/gpio/gpio-realtek-otto.c
 +++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -55,9 +55,12 @@
- struct realtek_gpio_ctrl {
- 	struct gpio_chip gc;
- 	void __iomem *base;
-+	void __iomem *cpumap_base;
+@@ -58,6 +58,8 @@ struct realtek_gpio_ctrl {
  	raw_spinlock_t lock;
  	u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
  	u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
@@ -13,7 +25,7 @@
  };
  
  /* Expand with more flags as devices with other quirks are added */
-@@ -69,6 +72,16 @@ enum realtek_gpio_flags {
+@@ -69,6 +71,11 @@ enum realtek_gpio_flags {
  	 * line the IRQ handler was assigned to, causing uncaught interrupts.
  	 */
  	GPIO_INTERRUPTS_DISABLED = BIT(0),
@@ -22,15 +34,10 @@
 +	 * fields, and [BA, DC] for 2-bit fields.
 +	 */
 +	GPIO_PORTS_REVERSED = BIT(1),
-+	/*
-+	 * Interrupts can be enabled per cpu. This requires a secondary IO
-+	 * range, where the per-cpu enable masks are located.
-+	 */
-+	GPIO_INTERRUPTS_PER_CPU = BIT(2),
  };
  
  static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
-@@ -86,21 +99,50 @@ static struct realtek_gpio_ctrl *irq_dat
+@@ -86,21 +93,50 @@ static struct realtek_gpio_ctrl *irq_dat
   * port. The two interrupt mask registers store two bits per GPIO, so use u16
   * values.
   */
@@ -84,34 +91,7 @@
  }
  
  /* Set the rising and falling edge mask bits for a GPIO port pin */
-@@ -222,6 +264,12 @@ static int realtek_gpio_irq_init(struct
- 	for (port = 0; (port * 8) < gc->ngpio; port++) {
- 		realtek_gpio_write_imr(ctrl, port, 0, 0);
- 		realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
-+
-+		if (ctrl->cpumap_base) {
-+			/* Default CPU affinity to the first CPU */
-+			iowrite8(GENMASK(7, 0),
-+				ctrl->cpumap_base + ctrl->port_offset_u8(port));
-+		}
- 	}
- 
- 	return 0;
-@@ -246,6 +294,13 @@ static const struct of_device_id realtek
- 	{
- 		.compatible = "realtek,rtl8390-gpio",
- 	},
-+	{
-+		.compatible = "realtek,rtl9300-gpio",
-+		.data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
-+	},
-+	{
-+		.compatible = "realtek,rtl9310-gpio",
-+	},
- 	{}
- };
- MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
-@@ -253,12 +308,14 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
+@@ -253,6 +289,7 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
  static int realtek_gpio_probe(struct platform_device *pdev)
  {
  	struct device *dev = &pdev->dev;
@@ -119,14 +99,7 @@
  	unsigned int dev_flags;
  	struct gpio_irq_chip *girq;
  	struct realtek_gpio_ctrl *ctrl;
- 	u32 ngpios;
- 	int err, irq;
- 
-+	pr_info("%s probing RTL GPIO\n", __func__);
- 	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
- 	if (!ctrl)
- 		return -ENOMEM;
-@@ -280,10 +337,21 @@ static int realtek_gpio_probe(struct pla
+@@ -280,10 +317,20 @@ static int realtek_gpio_probe(struct pla
  
  	raw_spin_lock_init(&ctrl->lock);
  
@@ -134,8 +107,7 @@
 +		bgpio_flags = 0;
 +		ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
 +		ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
-+	}
-+	else {
++	} else {
 +		bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
 +		ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
 +		ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
@@ -149,17 +121,3 @@
  	if (err) {
  		dev_err(dev, "unable to init generic GPIO");
  		return err;
-@@ -308,6 +376,13 @@ static int realtek_gpio_probe(struct pla
- 		girq->init_hw = realtek_gpio_irq_init;
- 	}
- 
-+	if (dev_flags & GPIO_INTERRUPTS_PER_CPU) {
-+		ctrl->cpumap_base = devm_platform_ioremap_resource(pdev, 1);
-+		if (IS_ERR(ctrl->cpumap_base))
-+			return dev_err_probe(dev, PTR_ERR(ctrl->cpumap_base),
-+				"IRQ CPU map registers not defined");
-+	}
-+
- 	return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
- }
- 
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch b/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
new file mode 100644
index 000000000000..8f5d571ea2f7
--- /dev/null
+++ b/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
@@ -0,0 +1,153 @@
+From 95fa6dbe58f286a8f87cb37b7516232eb678de2d Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander at svanheule.net>
+Date: Sat, 9 Apr 2022 21:55:48 +0200
+Subject: [PATCH 3/6] gpio: realtek-otto: Support per-cpu interrupts
+
+On SoCs with multiple cores, it is possible that the GPIO interrupt
+controller supports assigning specific pins to one or more cores.
+
+IRQ balancing can be performed on a line-by-line basis if the parent
+interrupt is routed to all available cores, which is the default upon
+initialisation.
+
+Signed-off-by: Sander Vanheule <sander at svanheule.net>
+Signed-off-by: Bartosz Golaszewski <brgl at bgdev.pl>
+---
+ drivers/gpio/gpio-realtek-otto.c | 75 +++++++++++++++++++++++++++++++-
+ 1 file changed, 74 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-realtek-otto.c
++++ b/drivers/gpio/gpio-realtek-otto.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ 
+ #include <linux/gpio/driver.h>
++#include <linux/cpumask.h>
+ #include <linux/irq.h>
+ #include <linux/minmax.h>
+ #include <linux/mod_devicetable.h>
+@@ -55,6 +56,8 @@
+ struct realtek_gpio_ctrl {
+ 	struct gpio_chip gc;
+ 	void __iomem *base;
++	void __iomem *cpumask_base;
++	struct cpumask cpu_irq_maskable;
+ 	raw_spinlock_t lock;
+ 	u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
+ 	u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
+@@ -76,6 +79,11 @@ enum realtek_gpio_flags {
+ 	 * fields, and [BA, DC] for 2-bit fields.
+ 	 */
+ 	GPIO_PORTS_REVERSED = BIT(1),
++	/*
++	 * Interrupts can be enabled per cpu. This requires a secondary IO
++	 * range, where the per-cpu enable masks are located.
++	 */
++	GPIO_INTERRUPTS_PER_CPU = BIT(2),
+ };
+ 
+ static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
+@@ -250,14 +258,61 @@ static void realtek_gpio_irq_handler(str
+ 	chained_irq_exit(irq_chip, desc);
+ }
+ 
++static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
++	unsigned int port, int cpu)
++{
++	return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
++		REALTEK_GPIO_PORTS_PER_BANK * cpu;
++}
++
++static int realtek_gpio_irq_set_affinity(struct irq_data *data,
++	const struct cpumask *dest, bool force)
++{
++	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
++	unsigned int line = irqd_to_hwirq(data);
++	unsigned int port = line / 8;
++	unsigned int port_pin = line % 8;
++	void __iomem *irq_cpu_mask;
++	unsigned long flags;
++	int cpu;
++	u8 v;
++
++	if (!ctrl->cpumask_base)
++		return -ENXIO;
++
++	raw_spin_lock_irqsave(&ctrl->lock, flags);
++
++	for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
++		irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
++		v = ioread8(irq_cpu_mask);
++
++		if (cpumask_test_cpu(cpu, dest))
++			v |= BIT(port_pin);
++		else
++			v &= ~BIT(port_pin);
++
++		iowrite8(v, irq_cpu_mask);
++	}
++
++	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
++
++	irq_data_update_effective_affinity(data, dest);
++
++	return 0;
++}
++
+ static int realtek_gpio_irq_init(struct gpio_chip *gc)
+ {
+ 	struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
+ 	unsigned int port;
++	int cpu;
+ 
+ 	for (port = 0; (port * 8) < gc->ngpio; port++) {
+ 		realtek_gpio_write_imr(ctrl, port, 0, 0);
+ 		realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
++
++		for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
++			iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
+ 	}
+ 
+ 	return 0;
+@@ -269,6 +324,7 @@ static struct irq_chip realtek_gpio_irq_
+ 	.irq_mask = realtek_gpio_irq_mask,
+ 	.irq_unmask = realtek_gpio_irq_unmask,
+ 	.irq_set_type = realtek_gpio_irq_set_type,
++	.irq_set_affinity = realtek_gpio_irq_set_affinity,
+ };
+ 
+ static const struct of_device_id realtek_gpio_of_match[] = {
+@@ -293,8 +349,10 @@ static int realtek_gpio_probe(struct pla
+ 	unsigned int dev_flags;
+ 	struct gpio_irq_chip *girq;
+ 	struct realtek_gpio_ctrl *ctrl;
++	struct resource *res;
+ 	u32 ngpios;
+-	int err, irq;
++	unsigned int nr_cpus;
++	int cpu, err, irq;
+ 
+ 	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ 	if (!ctrl)
+@@ -355,6 +413,21 @@ static int realtek_gpio_probe(struct pla
+ 		girq->init_hw = realtek_gpio_irq_init;
+ 	}
+ 
++	cpumask_clear(&ctrl->cpu_irq_maskable);
++
++	if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {
++		ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
++		if (IS_ERR(ctrl->cpumask_base))
++			return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),
++				"missing CPU IRQ mask registers");
++
++		nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;
++		nr_cpus = min(nr_cpus, num_present_cpus());
++
++		for (cpu = 0; cpu < nr_cpus; cpu++)
++			cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);
++	}
++
+ 	return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
+ }
+ 
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch b/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch
new file mode 100644
index 000000000000..536c85740a6b
--- /dev/null
+++ b/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch
@@ -0,0 +1,29 @@
+From deaf1cecdeb052cdb5e92fd642016198724b44a4 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander at svanheule.net>
+Date: Sat, 9 Apr 2022 21:55:49 +0200
+Subject: [PATCH 4/6] gpio: realtek-otto: Add RTL930x support
+
+The RTL930x SoC series has support for 24 GPIOs, with the port order
+reversed compared to RTL838x and RTL839x. The RTL930x series also has
+two CPUs (VPEs) and can distribute individual GPIO interrupts between
+them.
+
+Signed-off-by: Sander Vanheule <sander at svanheule.net>
+Signed-off-by: Bartosz Golaszewski <brgl at bgdev.pl>
+---
+ drivers/gpio/gpio-realtek-otto.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpio/gpio-realtek-otto.c
++++ b/drivers/gpio/gpio-realtek-otto.c
+@@ -338,6 +338,10 @@ static const struct of_device_id realtek
+ 	{
+ 		.compatible = "realtek,rtl8390-gpio",
+ 	},
++	{
++		.compatible = "realtek,rtl9300-gpio",
++		.data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
++	},
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch b/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch
new file mode 100644
index 000000000000..16990ce053ea
--- /dev/null
+++ b/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch
@@ -0,0 +1,30 @@
+From d3bf3dc4bbbf6109bd9b4bd60089d36205ec4a37 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander at svanheule.net>
+Date: Sat, 9 Apr 2022 21:55:51 +0200
+Subject: [PATCH 6/6] gpio: realtek-otto: Add RTL931x support
+
+The RTL931x SoC series has support for 32 GPIOs, although not all lines
+may be broken out to a physical pad.
+
+The GPIO bank's parent interrupt can be routed to either or both of the
+SoC's CPU cores by the GIC. Line-by-line IRQ balancing is not possible
+on these SoCs.
+
+Signed-off-by: Sander Vanheule <sander at svanheule.net>
+Signed-off-by: Bartosz Golaszewski <brgl at bgdev.pl>
+---
+ drivers/gpio/gpio-realtek-otto.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpio/gpio-realtek-otto.c
++++ b/drivers/gpio/gpio-realtek-otto.c
+@@ -342,6 +342,9 @@ static const struct of_device_id realtek
+ 		.compatible = "realtek,rtl9300-gpio",
+ 		.data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
+ 	},
++	{
++		.compatible = "realtek,rtl9310-gpio",
++	},
+ 	{}
+ };
+ MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
-- 
2.35.1




More information about the openwrt-devel mailing list