realtek: replace RTL93xx GPIO patches
[openwrt/staging/wigyori.git] / target / linux / realtek / patches-5.10 / 021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
1 From 95fa6dbe58f286a8f87cb37b7516232eb678de2d Mon Sep 17 00:00:00 2001
2 From: Sander Vanheule <sander@svanheule.net>
3 Date: Sat, 9 Apr 2022 21:55:48 +0200
4 Subject: [PATCH 3/6] gpio: realtek-otto: Support per-cpu interrupts
5
6 On SoCs with multiple cores, it is possible that the GPIO interrupt
7 controller supports assigning specific pins to one or more cores.
8
9 IRQ balancing can be performed on a line-by-line basis if the parent
10 interrupt is routed to all available cores, which is the default upon
11 initialisation.
12
13 Signed-off-by: Sander Vanheule <sander@svanheule.net>
14 Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
15 ---
16 drivers/gpio/gpio-realtek-otto.c | 75 +++++++++++++++++++++++++++++++-
17 1 file changed, 74 insertions(+), 1 deletion(-)
18
19 --- a/drivers/gpio/gpio-realtek-otto.c
20 +++ b/drivers/gpio/gpio-realtek-otto.c
21 @@ -1,6 +1,7 @@
22 // SPDX-License-Identifier: GPL-2.0-only
23
24 #include <linux/gpio/driver.h>
25 +#include <linux/cpumask.h>
26 #include <linux/irq.h>
27 #include <linux/minmax.h>
28 #include <linux/mod_devicetable.h>
29 @@ -55,6 +56,8 @@
30 struct realtek_gpio_ctrl {
31 struct gpio_chip gc;
32 void __iomem *base;
33 + void __iomem *cpumask_base;
34 + struct cpumask cpu_irq_maskable;
35 raw_spinlock_t lock;
36 u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
37 u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
38 @@ -76,6 +79,11 @@ enum realtek_gpio_flags {
39 * fields, and [BA, DC] for 2-bit fields.
40 */
41 GPIO_PORTS_REVERSED = BIT(1),
42 + /*
43 + * Interrupts can be enabled per cpu. This requires a secondary IO
44 + * range, where the per-cpu enable masks are located.
45 + */
46 + GPIO_INTERRUPTS_PER_CPU = BIT(2),
47 };
48
49 static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
50 @@ -250,14 +258,61 @@ static void realtek_gpio_irq_handler(str
51 chained_irq_exit(irq_chip, desc);
52 }
53
54 +static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
55 + unsigned int port, int cpu)
56 +{
57 + return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
58 + REALTEK_GPIO_PORTS_PER_BANK * cpu;
59 +}
60 +
61 +static int realtek_gpio_irq_set_affinity(struct irq_data *data,
62 + const struct cpumask *dest, bool force)
63 +{
64 + struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
65 + unsigned int line = irqd_to_hwirq(data);
66 + unsigned int port = line / 8;
67 + unsigned int port_pin = line % 8;
68 + void __iomem *irq_cpu_mask;
69 + unsigned long flags;
70 + int cpu;
71 + u8 v;
72 +
73 + if (!ctrl->cpumask_base)
74 + return -ENXIO;
75 +
76 + raw_spin_lock_irqsave(&ctrl->lock, flags);
77 +
78 + for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
79 + irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
80 + v = ioread8(irq_cpu_mask);
81 +
82 + if (cpumask_test_cpu(cpu, dest))
83 + v |= BIT(port_pin);
84 + else
85 + v &= ~BIT(port_pin);
86 +
87 + iowrite8(v, irq_cpu_mask);
88 + }
89 +
90 + raw_spin_unlock_irqrestore(&ctrl->lock, flags);
91 +
92 + irq_data_update_effective_affinity(data, dest);
93 +
94 + return 0;
95 +}
96 +
97 static int realtek_gpio_irq_init(struct gpio_chip *gc)
98 {
99 struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
100 unsigned int port;
101 + int cpu;
102
103 for (port = 0; (port * 8) < gc->ngpio; port++) {
104 realtek_gpio_write_imr(ctrl, port, 0, 0);
105 realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
106 +
107 + for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
108 + iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
109 }
110
111 return 0;
112 @@ -269,6 +324,7 @@ static struct irq_chip realtek_gpio_irq_
113 .irq_mask = realtek_gpio_irq_mask,
114 .irq_unmask = realtek_gpio_irq_unmask,
115 .irq_set_type = realtek_gpio_irq_set_type,
116 + .irq_set_affinity = realtek_gpio_irq_set_affinity,
117 };
118
119 static const struct of_device_id realtek_gpio_of_match[] = {
120 @@ -293,8 +349,10 @@ static int realtek_gpio_probe(struct pla
121 unsigned int dev_flags;
122 struct gpio_irq_chip *girq;
123 struct realtek_gpio_ctrl *ctrl;
124 + struct resource *res;
125 u32 ngpios;
126 - int err, irq;
127 + unsigned int nr_cpus;
128 + int cpu, err, irq;
129
130 ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
131 if (!ctrl)
132 @@ -355,6 +413,21 @@ static int realtek_gpio_probe(struct pla
133 girq->init_hw = realtek_gpio_irq_init;
134 }
135
136 + cpumask_clear(&ctrl->cpu_irq_maskable);
137 +
138 + if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {
139 + ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
140 + if (IS_ERR(ctrl->cpumask_base))
141 + return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),
142 + "missing CPU IRQ mask registers");
143 +
144 + nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;
145 + nr_cpus = min(nr_cpus, num_present_cpus());
146 +
147 + for (cpu = 0; cpu < nr_cpus; cpu++)
148 + cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);
149 + }
150 +
151 return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
152 }
153