linux/drivers/pinctrl
Horatiu Vultur c297561bc9 pinctrl: ocelot: Fix interrupt controller
When an external device generated a level based interrupt then the
interrupt controller could miss the interrupt. The reason is that the
interrupt controller can detect only link changes.

In the following example, if there is a PHY that generates an interrupt
then the following would happen. The GPIO detected that the interrupt
line changed, and then the 'ocelot_irq_handler' was called. Here it
detects which GPIO line saw the change and for that will call the
following:
1. irq_mask
2. phy interrupt routine
3. irq_eoi
4. irq_unmask

And this works fine for simple cases, but if the PHY generates many
interrupts, for example when doing PTP timestamping, then the following
could happen. Again the function 'ocelot_irq_handler' will be called
and then from here the following could happen:
1. irq_mask
2. phy interrupt routine
3. irq_eoi
4. irq_unmask

Right before step 3(irq_eoi), the PHY will generate another interrupt.
Now the interrupt controller will acknowledge the change in the
interrupt line. So we miss the interrupt.

A solution will be to use 'handle_level_irq' instead of
'handle_fasteoi_irq', because for this will change routine order of
handling the interrupt.
1. irq_mask
2. irq_ack
3. phy interrupt routine
4. irq_unmask

And now if the PHY will generate a new interrupt before irq_unmask, the
interrupt controller will detect this because it already acknowledge the
change in interrupt line at step 2(irq_ack).

But this is not the full solution because there is another issue. In
case there are 2 PHYs that share the interrupt line. For example phy1
generates an interrupt, then the following can happen:
1.irq_mask
2.irq_ack
3.phy0 interrupt routine
4.phy1 interrupt routine
5.irq_unmask

In case phy0 will generate an interrupt while clearing the interrupt
source in phy1, then the interrupt line will be kept down by phy0. So
the interrupt controller will not see any changes in the interrupt line.
The solution here is to update 'irq_unmask' such that it can detect if
the interrupt line is still active or not. And if it is active then call
again the procedure to clear the interrupts. But we don't want to do it
every time, only if we know that the interrupt controller has not seen
already that the interrupt line has changed.

While at this, add support also for IRQ_TYPE_LEVEL_LOW.

Fixes: be36abb71d ("pinctrl: ocelot: add support for interrupt controller")
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Link: https://lore.kernel.org/r/20220909145942.844102-1-horatiu.vultur@microchip.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2022-09-14 15:00:16 +02:00
..
actions
aspeed Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
bcm Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
berlin pinctrl: berlin: bg4ct: Use devm_platform_*ioremap_resource() APIs 2022-05-22 22:45:47 +02:00
cirrus
freescale Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
intel Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
mediatek pinctrl: mediatek: mt8192: Fix compile warnings 2022-06-27 01:56:52 +02:00
meson intel-gpio for v5.19-1 2022-05-04 23:15:21 +02:00
mvebu Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
nomadik pinctrl: nomadik: Fix refcount leak in nmk_pinctrl_dt_subnode_to_map 2022-06-15 16:04:01 +02:00
nuvoton Pin control bulk changes for the v5.19 series: 2022-05-28 11:15:54 -07:00
pxa
qcom pinctrl: qcom: sc8180x: Fix wrong pin numbers 2022-08-22 10:57:07 +02:00
ralink pinctrl: ralink: Check for null return of devm_kcalloc 2022-07-11 14:40:17 +02:00
renesas Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
samsung pinctrl: samsung: do not use bindings header with constants 2022-06-28 15:55:20 +02:00
spear
sprd
stm32 pinctrl: stm32: fix optional IRQ support to gpios 2022-06-28 16:12:40 +02:00
sunplus pinctrl: sunplus: Add check for kcalloc 2022-07-11 15:04:19 +02:00
sunxi pinctrl: sunxi: Fix name for A100 R_PIO 2022-08-26 10:37:24 +02:00
tegra pinctrl: tegra: tegra194: drop unused pin groups 2022-05-04 23:40:05 +02:00
ti
uniphier
visconti
vt8500
core.c pinctrl: core: Use device_match_of_node() helper 2022-07-18 11:38:37 +02:00
core.h
devicetree.c pinctrl: devicetree: Delete usage of driver_deferred_probe_check_state() 2022-06-10 15:57:54 +02:00
devicetree.h
Kconfig Pin control bulk changes for v6.0: 2022-08-10 11:01:44 -07:00
Makefile pinctrl: nuvoton: Add driver for WPCM450 2022-03-15 01:16:20 +01:00
pinconf-generic.c pinctrl: pinconf-generic: Print arguments for bias-pull-* 2022-03-15 01:24:15 +01:00
pinconf.c
pinconf.h
pinctrl-amd.c pinctrl: amd: Fix an unused variable 2022-08-03 20:14:52 +02:00
pinctrl-amd.h pinctrl: amd: Implement pinmux functionality 2022-06-15 15:54:20 +02:00
pinctrl-apple-gpio.c pinctrl: apple: Use a raw spinlock for the regmap 2022-05-25 09:37:44 +02:00
pinctrl-artpec6.c
pinctrl-as3722.c treewide: Replace GPLv2 boilerplate/reference with SPDX - gpl-2.0_318.RULE 2022-06-10 14:51:36 +02:00
pinctrl-at91-pio4.c pinctrl: at91-pio4: remove #ifdef CONFIG_PM_SLEEP 2022-07-18 11:38:36 +02:00
pinctrl-at91.c pinctrl: at91: Fix typo 'the the' in comment 2022-07-26 09:53:35 +02:00
pinctrl-at91.h
pinctrl-axp209.c pinctrl: axp209: Support the AXP221/AXP223/AXP809 variant 2022-06-30 14:05:57 +02:00
pinctrl-bm1880.c
pinctrl-da850-pupd.c
pinctrl-da9062.c
pinctrl-digicolor.c
pinctrl-equilibrium.c pinctrl: equilibrium: Switch to use fwnode instead of of_node 2022-05-09 13:46:51 +02:00
pinctrl-equilibrium.h pinctrl: equilibrium: Switch to use fwnode instead of of_node 2022-05-09 13:46:51 +02:00
pinctrl-falcon.c
pinctrl-gemini.c
pinctrl-ingenic.c pinctrl: ingenic: Convert to immutable irq chip 2022-06-28 13:45:21 +02:00
pinctrl-k210.c pinctrl: k210: Fix bias-pull-up 2022-02-11 02:19:47 +01:00
pinctrl-keembay.c
pinctrl-lantiq.c
pinctrl-lantiq.h
pinctrl-lpc18xx.c
pinctrl-max77620.c pinctrl: max77620: drop unneeded MODULE_ALIAS 2022-04-22 22:56:46 +02:00
pinctrl-mcp23s08_i2c.c
pinctrl-mcp23s08_spi.c
pinctrl-mcp23s08.c
pinctrl-mcp23s08.h
pinctrl-microchip-sgpio.c pinctrl: microchip-sgpio: Switch to use fwnode instead of of_node 2022-05-09 13:47:49 +02:00
pinctrl-ocelot.c pinctrl: ocelot: Fix interrupt controller 2022-09-14 15:00:16 +02:00
pinctrl-oxnas.c
pinctrl-palmas.c treewide: Replace GPLv2 boilerplate/reference with SPDX - gpl-2.0_318.RULE 2022-06-10 14:51:36 +02:00
pinctrl-pic32.c
pinctrl-pic32.h
pinctrl-pistachio.c pinctrl: pistachio: fix use of irq_of_parse_and_map() 2022-04-24 16:24:09 +02:00
pinctrl-rk805.c
pinctrl-rockchip.c Linux 5.18-rc5 2022-05-01 23:25:10 +02:00
pinctrl-rockchip.h pinctrl/rockchip: add rk3588 support 2022-04-29 00:55:02 +02:00
pinctrl-single.c
pinctrl-st.c
pinctrl-starfive.c pinctrl: starfive: Serialize adding groups and functions 2022-07-11 10:22:57 +02:00
pinctrl-stmfx.c
pinctrl-sx150x.c
pinctrl-tb10x.c
pinctrl-thunderbay.c pinctrl: thunderbay: Use devm_platform_ioremap_resource() 2022-04-23 00:01:55 +02:00
pinctrl-utils.c treewide: Replace GPLv2 boilerplate/reference with SPDX - gpl-2.0_318.RULE 2022-06-10 14:51:36 +02:00
pinctrl-utils.h treewide: Replace GPLv2 boilerplate/reference with SPDX - gpl-2.0_318.RULE 2022-06-10 14:51:36 +02:00
pinctrl-xway.c
pinctrl-zynq.c pinctrl: zynq: use module_platform_driver to simplify the code 2022-03-15 01:46:13 +01:00
pinctrl-zynqmp.c pinctrl: pinctrl-zynqmp: Fix kernel-doc warning 2022-06-28 10:29:39 +02:00
pinmux.c
pinmux.h