9c043b71269e652a7994eb827aaf579e54da464e
[openwrt/staging/jow.git] / target / linux / realtek / patches-5.15 / 317-gpio-realtek-otto-switch-to-32-bit-I-O.patch
1 From ee0175b3b44288c74d5292c2a9c2c154f6c0317e Mon Sep 17 00:00:00 2001
2 From: Sander Vanheule <sander@svanheule.net>
3 Date: Sun, 7 Aug 2022 21:21:15 +0200
4 Subject: [PATCH] gpio: realtek-otto: switch to 32-bit I/O
5
6 By using 16-bit I/O on the GPIO peripheral, which is apparently not safe
7 on MIPS, the IMR can end up containing garbage. This then results in
8 interrupt triggers for lines that don't have an interrupt handler
9 associated. The irq_desc lookup fails, and the ISR will not be cleared,
10 keeping the CPU busy until reboot, or until another IMR operation
11 restores the correct value. This situation appears to happen very
12 rarely, for < 0.5% of IMR writes.
13
14 Instead of using 8-bit or 16-bit I/O operations on the 32-bit memory
15 mapped peripheral registers, switch to using 32-bit I/O only, operating
16 on the entire bank for all single bit line settings. For 2-bit line
17 settings, with 16-bit port values, stick to manual (un)packing.
18
19 This issue has been seen on RTL8382M (HPE 1920-16G), RTL8391M (Netgear
20 GS728TP v2), and RTL8393M (D-Link DGS-1210-52 F3, Zyxel GS1900-48).
21
22 Reported-by: Luiz Angelo Daros de Luca <luizluca@gmail.com> # DGS-1210-52
23 Reported-by: Birger Koblitz <mail@birger-koblitz.de> # GS728TP
24 Reported-by: Jan Hoffmann <jan@3e8.eu> # 1920-16G
25 Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
26 Signed-off-by: Sander Vanheule <sander@svanheule.net>
27 Cc: Paul Cercueil <paul@crapouillou.net>
28 Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
29 Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
30
31 Update patch for missing upstream changes:
32 - commit a01a40e33499 ("gpio: realtek-otto: Make the irqchip immutable")
33 - commit dbd1c54fc820 ("gpio: Bulk conversion to generic_handle_domain_irq()")
34 Signed-off-by: Sander Vanheule <sander@svanheule.net>
35
36 ---
37 drivers/gpio/gpio-realtek-otto.c | 166 ++++++++++++++++---------------
38 1 file changed, 85 insertions(+), 81 deletions(-)
39
40 --- a/drivers/gpio/gpio-realtek-otto.c
41 +++ b/drivers/gpio/gpio-realtek-otto.c
42 @@ -46,10 +46,20 @@
43 * @lock: Lock for accessing the IRQ registers and values
44 * @intr_mask: Mask for interrupts lines
45 * @intr_type: Interrupt type selection
46 + * @bank_read: Read a bank setting as a single 32-bit value
47 + * @bank_write: Write a bank setting as a single 32-bit value
48 + * @imr_line_pos: Bit shift of an IRQ line's IMR value.
49 + *
50 + * The DIR, DATA, and ISR registers consist of four 8-bit port values, packed
51 + * into a single 32-bit register. Use @bank_read (@bank_write) to get (assign)
52 + * a value from (to) these registers. The IMR register consists of four 16-bit
53 + * port values, packed into two 32-bit registers. Use @imr_line_pos to get the
54 + * bit shift of the 2-bit field for a line's IMR settings. Shifts larger than
55 + * 32 overflow into the second register.
56 *
57 * Because the interrupt mask register (IMR) combines the function of IRQ type
58 * selection and masking, two extra values are stored. @intr_mask is used to
59 - * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
60 + * mask/unmask the interrupts for a GPIO line, and @intr_type is used to store
61 * the selected interrupt types. The logical AND of these values is written to
62 * IMR on changes.
63 */
64 @@ -59,10 +69,11 @@ struct realtek_gpio_ctrl {
65 void __iomem *cpumask_base;
66 struct cpumask cpu_irq_maskable;
67 raw_spinlock_t lock;
68 - u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
69 - u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
70 - unsigned int (*port_offset_u8)(unsigned int port);
71 - unsigned int (*port_offset_u16)(unsigned int port);
72 + u8 intr_mask[REALTEK_GPIO_MAX];
73 + u8 intr_type[REALTEK_GPIO_MAX];
74 + u32 (*bank_read)(void __iomem *reg);
75 + void (*bank_write)(void __iomem *reg, u32 value);
76 + unsigned int (*line_imr_pos)(unsigned int line);
77 };
78
79 /* Expand with more flags as devices with other quirks are added */
80 @@ -101,14 +112,22 @@ static struct realtek_gpio_ctrl *irq_dat
81 * port. The two interrupt mask registers store two bits per GPIO, so use u16
82 * values.
83 */
84 -static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
85 +static u32 realtek_gpio_bank_read_swapped(void __iomem *reg)
86 +{
87 + return ioread32be(reg);
88 +}
89 +
90 +static void realtek_gpio_bank_write_swapped(void __iomem *reg, u32 value)
91 {
92 - return port;
93 + iowrite32be(value, reg);
94 }
95
96 -static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
97 +static unsigned int realtek_gpio_line_imr_pos_swapped(unsigned int line)
98 {
99 - return 2 * port;
100 + unsigned int port_pin = line % 8;
101 + unsigned int port = line / 8;
102 +
103 + return 2 * (8 * (port ^ 1) + port_pin);
104 }
105
106 /*
107 @@ -119,64 +138,65 @@ static unsigned int realtek_gpio_port_of
108 * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
109 * second ports 3 and 2.
110 */
111 -static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
112 +static u32 realtek_gpio_bank_read(void __iomem *reg)
113 {
114 - return 3 - port;
115 + return ioread32(reg);
116 }
117
118 -static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
119 +static void realtek_gpio_bank_write(void __iomem *reg, u32 value)
120 {
121 - return 2 * (port ^ 1);
122 + iowrite32(value, reg);
123 }
124
125 -static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
126 - unsigned int port, u16 irq_type, u16 irq_mask)
127 +static unsigned int realtek_gpio_line_imr_pos(unsigned int line)
128 {
129 - iowrite16(irq_type & irq_mask,
130 - ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
131 + return 2 * line;
132 }
133
134 -static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
135 - unsigned int port, u8 mask)
136 +static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, u32 mask)
137 {
138 - iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
139 + ctrl->bank_write(ctrl->base + REALTEK_GPIO_REG_ISR, mask);
140 }
141
142 -static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
143 +static u32 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl)
144 {
145 - return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
146 + return ctrl->bank_read(ctrl->base + REALTEK_GPIO_REG_ISR);
147 }
148
149 -/* Set the rising and falling edge mask bits for a GPIO port pin */
150 -static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
151 +/* Set the rising and falling edge mask bits for a GPIO pin */
152 +static void realtek_gpio_update_line_imr(struct realtek_gpio_ctrl *ctrl, unsigned int line)
153 {
154 - return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
155 + void __iomem *reg = ctrl->base + REALTEK_GPIO_REG_IMR;
156 + unsigned int line_shift = ctrl->line_imr_pos(line);
157 + unsigned int shift = line_shift % 32;
158 + u32 irq_type = ctrl->intr_type[line];
159 + u32 irq_mask = ctrl->intr_mask[line];
160 + u32 reg_val;
161 +
162 + reg += 4 * (line_shift / 32);
163 + reg_val = ioread32(reg);
164 + reg_val &= ~(REALTEK_GPIO_IMR_LINE_MASK << shift);
165 + reg_val |= (irq_type & irq_mask & REALTEK_GPIO_IMR_LINE_MASK) << shift;
166 + iowrite32(reg_val, reg);
167 }
168
169 static void realtek_gpio_irq_ack(struct irq_data *data)
170 {
171 struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
172 irq_hw_number_t line = irqd_to_hwirq(data);
173 - unsigned int port = line / 8;
174 - unsigned int port_pin = line % 8;
175
176 - realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
177 + realtek_gpio_clear_isr(ctrl, BIT(line));
178 }
179
180 static void realtek_gpio_irq_unmask(struct irq_data *data)
181 {
182 struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
183 unsigned int line = irqd_to_hwirq(data);
184 - unsigned int port = line / 8;
185 - unsigned int port_pin = line % 8;
186 unsigned long flags;
187 - u16 m;
188
189 raw_spin_lock_irqsave(&ctrl->lock, flags);
190 - m = ctrl->intr_mask[port];
191 - m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
192 - ctrl->intr_mask[port] = m;
193 - realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
194 + ctrl->intr_mask[line] = REALTEK_GPIO_IMR_LINE_MASK;
195 + realtek_gpio_update_line_imr(ctrl, line);
196 raw_spin_unlock_irqrestore(&ctrl->lock, flags);
197 }
198
199 @@ -184,16 +204,11 @@ static void realtek_gpio_irq_mask(struct
200 {
201 struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
202 unsigned int line = irqd_to_hwirq(data);
203 - unsigned int port = line / 8;
204 - unsigned int port_pin = line % 8;
205 unsigned long flags;
206 - u16 m;
207
208 raw_spin_lock_irqsave(&ctrl->lock, flags);
209 - m = ctrl->intr_mask[port];
210 - m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
211 - ctrl->intr_mask[port] = m;
212 - realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
213 + ctrl->intr_mask[line] = 0;
214 + realtek_gpio_update_line_imr(ctrl, line);
215 raw_spin_unlock_irqrestore(&ctrl->lock, flags);
216 }
217
218 @@ -201,10 +216,8 @@ static int realtek_gpio_irq_set_type(str
219 {
220 struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
221 unsigned int line = irqd_to_hwirq(data);
222 - unsigned int port = line / 8;
223 - unsigned int port_pin = line % 8;
224 unsigned long flags;
225 - u16 type, t;
226 + u8 type;
227
228 switch (flow_type & IRQ_TYPE_SENSE_MASK) {
229 case IRQ_TYPE_EDGE_FALLING:
230 @@ -223,11 +236,8 @@ static int realtek_gpio_irq_set_type(str
231 irq_set_handler_locked(data, handle_edge_irq);
232
233 raw_spin_lock_irqsave(&ctrl->lock, flags);
234 - t = ctrl->intr_type[port];
235 - t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
236 - t |= realtek_gpio_imr_bits(port_pin, type);
237 - ctrl->intr_type[port] = t;
238 - realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
239 + ctrl->intr_type[line] = type;
240 + realtek_gpio_update_line_imr(ctrl, line);
241 raw_spin_unlock_irqrestore(&ctrl->lock, flags);
242
243 return 0;
244 @@ -238,31 +248,24 @@ static void realtek_gpio_irq_handler(str
245 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
246 struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
247 struct irq_chip *irq_chip = irq_desc_get_chip(desc);
248 - unsigned int lines_done;
249 - unsigned int port_pin_count;
250 unsigned int irq;
251 unsigned long status;
252 int offset;
253
254 chained_irq_enter(irq_chip, desc);
255
256 - for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
257 - status = realtek_gpio_read_isr(ctrl, lines_done / 8);
258 - port_pin_count = min(gc->ngpio - lines_done, 8U);
259 - for_each_set_bit(offset, &status, port_pin_count) {
260 - irq = irq_find_mapping(gc->irq.domain, offset + lines_done);
261 - generic_handle_irq(irq);
262 - }
263 + status = realtek_gpio_read_isr(ctrl);
264 + for_each_set_bit(offset, &status, gc->ngpio) {
265 + irq = irq_find_mapping(gc->irq.domain, offset);
266 + generic_handle_irq(irq);
267 }
268
269 chained_irq_exit(irq_chip, desc);
270 }
271
272 -static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
273 - unsigned int port, int cpu)
274 +static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl, int cpu)
275 {
276 - return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
277 - REALTEK_GPIO_PORTS_PER_BANK * cpu;
278 + return ctrl->cpumask_base + REALTEK_GPIO_PORTS_PER_BANK * cpu;
279 }
280
281 static int realtek_gpio_irq_set_affinity(struct irq_data *data,
282 @@ -270,12 +273,10 @@ static int realtek_gpio_irq_set_affinity
283 {
284 struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
285 unsigned int line = irqd_to_hwirq(data);
286 - unsigned int port = line / 8;
287 - unsigned int port_pin = line % 8;
288 void __iomem *irq_cpu_mask;
289 unsigned long flags;
290 int cpu;
291 - u8 v;
292 + u32 v;
293
294 if (!ctrl->cpumask_base)
295 return -ENXIO;
296 @@ -283,15 +284,15 @@ static int realtek_gpio_irq_set_affinity
297 raw_spin_lock_irqsave(&ctrl->lock, flags);
298
299 for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
300 - irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
301 - v = ioread8(irq_cpu_mask);
302 + irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
303 + v = ctrl->bank_read(irq_cpu_mask);
304
305 if (cpumask_test_cpu(cpu, dest))
306 - v |= BIT(port_pin);
307 + v |= BIT(line);
308 else
309 - v &= ~BIT(port_pin);
310 + v &= ~BIT(line);
311
312 - iowrite8(v, irq_cpu_mask);
313 + ctrl->bank_write(irq_cpu_mask, v);
314 }
315
316 raw_spin_unlock_irqrestore(&ctrl->lock, flags);
317 @@ -305,22 +306,23 @@ static int realtek_gpio_irq_init(struct
318 {
319 struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
320 void __iomem *irq_cpu_mask;
321 - unsigned int port;
322 + u32 mask_all = GENMASK(gc->ngpio - 1, 0);
323 + unsigned int line;
324 int cpu;
325
326 - for (port = 0; (port * 8) < gc->ngpio; port++) {
327 - realtek_gpio_write_imr(ctrl, port, 0, 0);
328 - realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
329 -
330 - /*
331 - * Uniprocessor builds assume a mask always contains one CPU,
332 - * so only start the loop if we have at least one maskable CPU.
333 - */
334 - if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
335 - for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
336 - irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
337 - iowrite8(GENMASK(7, 0), irq_cpu_mask);
338 - }
339 + for (line = 0; line < gc->ngpio; line++)
340 + realtek_gpio_update_line_imr(ctrl, line);
341 +
342 + realtek_gpio_clear_isr(ctrl, mask_all);
343 +
344 + /*
345 + * Uniprocessor builds assume a mask always contains one CPU,
346 + * so only start the loop if we have at least one maskable CPU.
347 + */
348 + if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
349 + for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
350 + irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
351 + ctrl->bank_write(irq_cpu_mask, mask_all);
352 }
353 }
354
355 @@ -393,12 +395,14 @@ static int realtek_gpio_probe(struct pla
356
357 if (dev_flags & GPIO_PORTS_REVERSED) {
358 bgpio_flags = 0;
359 - ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
360 - ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
361 + ctrl->bank_read = realtek_gpio_bank_read;
362 + ctrl->bank_write = realtek_gpio_bank_write;
363 + ctrl->line_imr_pos = realtek_gpio_line_imr_pos;
364 } else {
365 bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
366 - ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
367 - ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
368 + ctrl->bank_read = realtek_gpio_bank_read_swapped;
369 + ctrl->bank_write = realtek_gpio_bank_write_swapped;
370 + ctrl->line_imr_pos = realtek_gpio_line_imr_pos_swapped;
371 }
372
373 err = bgpio_init(&ctrl->gc, dev, 4,