diff options
Diffstat (limited to 'target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch')
-rw-r--r-- | target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch | 153 |
1 files changed, 0 insertions, 153 deletions
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 deleted file mode 100644 index 8f5d571ea2..0000000000 --- a/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 95fa6dbe58f286a8f87cb37b7516232eb678de2d Mon Sep 17 00:00:00 2001 -From: Sander Vanheule <sander@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@svanheule.net> -Signed-off-by: Bartosz Golaszewski <brgl@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); - } - |