diff mbox series

[v4,2/2] gpio: mxc: Always set GPIOs used as interrupt source to INPUT mode

Message ID 20220724224943.294057-2-marex@denx.de
State Superseded
Headers show
Series [v4,1/2] gpio: mxc: Protect GPIO irqchip RMW with bgpio spinlock | expand

Commit Message

Marek Vasut July 24, 2022, 10:49 p.m. UTC
Always configure GPIO pins which are used as interrupt source as INPUTs.
In case the default pin configuration is OUTPUT, or the prior stage does
configure the pins as OUTPUT, then Linux will not reconfigure the pin as
INPUT and no interrupts are received.

Always configure interrupt source GPIO pin as input to fix the above case.

Fixes: 07bd1a6cc7cbb ("MXC arch: Add gpio support for the whole platform")
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Loic Poulain <loic.poulain@linaro.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: NXP Linux Team <linux-imx@nxp.com>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Shawn Guo <shawnguo@kernel.org>
---
V2: Actually update and clear bits in GDIR register
V3: Rebase on top of new patch 1/2, expand CC list, add Fixes tag
V4: No change
---
 drivers/gpio/gpio-mxc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Linus Walleij July 26, 2022, 8:15 a.m. UTC | #1
On Mon, Jul 25, 2022 at 12:50 AM Marek Vasut <marex@denx.de> wrote:

> Always configure GPIO pins which are used as interrupt source as INPUTs.
> In case the default pin configuration is OUTPUT, or the prior stage does
> configure the pins as OUTPUT, then Linux will not reconfigure the pin as
> INPUT and no interrupts are received.
>
> Always configure interrupt source GPIO pin as input to fix the above case.
>
> Fixes: 07bd1a6cc7cbb ("MXC arch: Add gpio support for the whole platform")
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Loic Poulain <loic.poulain@linaro.org>
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: NXP Linux Team <linux-imx@nxp.com>
> Cc: Peng Fan <peng.fan@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
> ---
> V2: Actually update and clear bits in GDIR register
> V3: Rebase on top of new patch 1/2, expand CC list, add Fixes tag
> V4: No change

I understand what you are trying to achieve, and it makes sense.

There's is just this one generic GPIO-based driver that makes me
a little bit nervous here.

Consider:
drivers/media/cec/platform/cec-gpio/cec-gpio.c
Look what the driver is doing with the gpiod_* operations on it's
cec->cec_gpio.

A certain GPIO pin is switched back and forth between input and
output and in input mode, it is used to generate interrupts as well.

Will this still work fine with the MXC driver after this change?
At least it will be set to input mode twice, but I suppose that is
fine, it's not your fault that the frameworks are orthogonal.

Yours,
Linus Walleij
Marek Vasut July 26, 2022, 2:42 p.m. UTC | #2
On 7/26/22 10:15, Linus Walleij wrote:
> On Mon, Jul 25, 2022 at 12:50 AM Marek Vasut <marex@denx.de> wrote:
> 
>> Always configure GPIO pins which are used as interrupt source as INPUTs.
>> In case the default pin configuration is OUTPUT, or the prior stage does
>> configure the pins as OUTPUT, then Linux will not reconfigure the pin as
>> INPUT and no interrupts are received.
>>
>> Always configure interrupt source GPIO pin as input to fix the above case.
>>
>> Fixes: 07bd1a6cc7cbb ("MXC arch: Add gpio support for the whole platform")
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>> Cc: Linus Walleij <linus.walleij@linaro.org>
>> Cc: Loic Poulain <loic.poulain@linaro.org>
>> Cc: Marc Zyngier <maz@kernel.org>
>> Cc: NXP Linux Team <linux-imx@nxp.com>
>> Cc: Peng Fan <peng.fan@nxp.com>
>> Cc: Shawn Guo <shawnguo@kernel.org>
>> ---
>> V2: Actually update and clear bits in GDIR register
>> V3: Rebase on top of new patch 1/2, expand CC list, add Fixes tag
>> V4: No change
> 
> I understand what you are trying to achieve, and it makes sense.
> 
> There's is just this one generic GPIO-based driver that makes me
> a little bit nervous here.
> 
> Consider:
> drivers/media/cec/platform/cec-gpio/cec-gpio.c
> Look what the driver is doing with the gpiod_* operations on it's
> cec->cec_gpio.
> 
> A certain GPIO pin is switched back and forth between input and
> output and in input mode, it is used to generate interrupts as well.
> 
> Will this still work fine with the MXC driver after this change?
> At least it will be set to input mode twice, but I suppose that is
> fine, it's not your fault that the frameworks are orthogonal.

Ugh. I don't see why it shouldn't work, esp. if the CEC driver controls 
the direction and the default is input, but I wonder what other corner 
cases there are.
Hans Verkuil July 26, 2022, 3:13 p.m. UTC | #3
On 7/26/22 16:42, Marek Vasut wrote:
> On 7/26/22 10:15, Linus Walleij wrote:
>> On Mon, Jul 25, 2022 at 12:50 AM Marek Vasut <marex@denx.de> wrote:
>>
>>> Always configure GPIO pins which are used as interrupt source as INPUTs.
>>> In case the default pin configuration is OUTPUT, or the prior stage does
>>> configure the pins as OUTPUT, then Linux will not reconfigure the pin as
>>> INPUT and no interrupts are received.
>>>
>>> Always configure interrupt source GPIO pin as input to fix the above case.
>>>
>>> Fixes: 07bd1a6cc7cbb ("MXC arch: Add gpio support for the whole platform")
>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>> Cc: Linus Walleij <linus.walleij@linaro.org>
>>> Cc: Loic Poulain <loic.poulain@linaro.org>
>>> Cc: Marc Zyngier <maz@kernel.org>
>>> Cc: NXP Linux Team <linux-imx@nxp.com>
>>> Cc: Peng Fan <peng.fan@nxp.com>
>>> Cc: Shawn Guo <shawnguo@kernel.org>
>>> ---
>>> V2: Actually update and clear bits in GDIR register
>>> V3: Rebase on top of new patch 1/2, expand CC list, add Fixes tag
>>> V4: No change
>>
>> I understand what you are trying to achieve, and it makes sense.
>>
>> There's is just this one generic GPIO-based driver that makes me
>> a little bit nervous here.
>>
>> Consider:
>> drivers/media/cec/platform/cec-gpio/cec-gpio.c
>> Look what the driver is doing with the gpiod_* operations on it's
>> cec->cec_gpio.
>>
>> A certain GPIO pin is switched back and forth between input and
>> output and in input mode, it is used to generate interrupts as well.
>>
>> Will this still work fine with the MXC driver after this change?
>> At least it will be set to input mode twice, but I suppose that is
>> fine, it's not your fault that the frameworks are orthogonal.
> 
> Ugh. I don't see why it shouldn't work, esp. if the CEC driver controls the direction and the default is input, but I wonder what other corner cases there are.

FYI: you can easily test cec-gpio by adding something along these lines to the dts:

	cec-gpio {
		compatible = "cec-gpio";
		cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
	};

(this is from a Raspberry Pi). As long as the cec-gpios pin can be configured as a
pull up, then you're OK. It doesn't have to be connected to anything.

If the cec-gpio driver is enabled as well, then you should see a /dev/cec0 device.

If you can run 'cec-ctl --playback -p 1.0.0.0', then it works.

Another driver that switches direction is drivers/gpu/drm/i2c/tda998x_drv.c
where the irq line has to be configured as an output during calibration.
See tda998x_cec_calibration().

Regards,

	Hans
Linus Walleij July 26, 2022, 8:59 p.m. UTC | #4
On Mon, Jul 25, 2022 at 12:50 AM Marek Vasut <marex@denx.de> wrote:

> Always configure GPIO pins which are used as interrupt source as INPUTs.
> In case the default pin configuration is OUTPUT, or the prior stage does
> configure the pins as OUTPUT, then Linux will not reconfigure the pin as
> INPUT and no interrupts are received.
>
> Always configure interrupt source GPIO pin as input to fix the above case.
>
> Fixes: 07bd1a6cc7cbb ("MXC arch: Add gpio support for the whole platform")
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Loic Poulain <loic.poulain@linaro.org>
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: NXP Linux Team <linux-imx@nxp.com>
> Cc: Peng Fan <peng.fan@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>

It's up to the driver to deal with the final hardware state, and the
author knows what he's doing so:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij
Marek Vasut July 29, 2022, 3:01 a.m. UTC | #5
On 7/26/22 17:13, Hans Verkuil wrote:

[...]

> FYI: you can easily test cec-gpio by adding something along these lines to the dts:
> 
> 	cec-gpio {
> 		compatible = "cec-gpio";
> 		cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
> 	};
> 
> (this is from a Raspberry Pi). As long as the cec-gpios pin can be configured as a
> pull up, then you're OK. It doesn't have to be connected to anything.
> 
> If the cec-gpio driver is enabled as well, then you should see a /dev/cec0 device.
> 
> If you can run 'cec-ctl --playback -p 1.0.0.0', then it works.
> 
> Another driver that switches direction is drivers/gpu/drm/i2c/tda998x_drv.c
> where the irq line has to be configured as an output during calibration.
> See tda998x_cec_calibration().

Does this look OK ?

$ cec-ctl --playback -p 1.0.0.0
Driver Info:
         Driver Name                : cec-gpio
         Adapter Name               : cec-gpio
         Capabilities               : 0x000000af
                 Physical Address
                 Logical Addresses
                 Transmit
                 Passthrough
                 Monitor All
                 Monitor Pin
         Driver version             : 5.19.0
         Available Logical Addresses: 4
         Connector Info             : None
         Physical Address           : 1.0.0.0
         Logical Address Mask       : 0x0010
         CEC Version                : 2.0
         Vendor ID                  : 0x000c03 (HDMI)
         OSD Name                   : 'Playback'
         Logical Addresses          : 1 (Allow RC Passthrough)

           Logical Address          : 4 (Playback Device 1)
             Primary Device Type    : Playback
             Logical Address Type   : Playback
             All Device Types       : Playback
             RC TV Profile          : None
             Device Features        :
                 None

$ cec-compliance
Driver Info:
         Driver Name                : cec-gpio
         Adapter Name               : cec-gpio
         Capabilities               : 0x000000af
                 Physical Address
                 Logical Addresses
                 Transmit
                 Passthrough
                 Monitor All
                 Monitor Pin
         Driver version             : 5.19.0
         Available Logical Addresses: 4
         Connector Info             : None
         Physical Address           : 1.0.0.0
         Logical Address Mask       : 0x0010
         CEC Version                : 2.0
         Vendor ID                  : 0x000c03 (HDMI)
         OSD Name                   : 'Playback'
         Logical Addresses          : 1 (Allow RC Passthrough)

           Logical Address          : 4 (Playback Device 1)
             Primary Device Type    : Playback
             Logical Address Type   : Playback
             All Device Types       : Playback
             RC TV Profile          : None
             Device Features        :
                 None

Compliance test for cec-gpio device /dev/cec0:

     The test results mean the following:
         OK                    Supported correctly by the device.
         OK (Not Supported)    Not supported and not mandatory for the 
device.
         OK (Presumed)         Presumably supported.  Manually check to 
confirm.
         OK (Unexpected)       Supported correctly but is not expected 
to be supported for this device.
         OK (Refused)          Supported by the device, but was refused.
         OK (Expected Failure) Failed but this was expected (see -e option).
         FAIL                  Failed and was expected to be supported 
by this device.

Find remote devices:
         Polling: OK

FAIL: No remote devices found, exiting.
Hans Verkuil July 29, 2022, 6:56 a.m. UTC | #6
Hi Marek,

On 29/07/2022 05:01, Marek Vasut wrote:
> On 7/26/22 17:13, Hans Verkuil wrote:
> 
> [...]
> 
>> FYI: you can easily test cec-gpio by adding something along these lines to the dts:
>>
>>     cec-gpio {
>>         compatible = "cec-gpio";
>>         cec-gpios = <&gpio 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
>>     };
>>
>> (this is from a Raspberry Pi). As long as the cec-gpios pin can be configured as a
>> pull up, then you're OK. It doesn't have to be connected to anything.
>>
>> If the cec-gpio driver is enabled as well, then you should see a /dev/cec0 device.
>>
>> If you can run 'cec-ctl --playback -p 1.0.0.0', then it works.
>>
>> Another driver that switches direction is drivers/gpu/drm/i2c/tda998x_drv.c
>> where the irq line has to be configured as an output during calibration.
>> See tda998x_cec_calibration().
> 
> Does this look OK ?
> 
> $ cec-ctl --playback -p 1.0.0.0
> Driver Info:
>         Driver Name                : cec-gpio
>         Adapter Name               : cec-gpio
>         Capabilities               : 0x000000af
>                 Physical Address
>                 Logical Addresses
>                 Transmit
>                 Passthrough
>                 Monitor All
>                 Monitor Pin
>         Driver version             : 5.19.0
>         Available Logical Addresses: 4
>         Connector Info             : None
>         Physical Address           : 1.0.0.0
>         Logical Address Mask       : 0x0010
>         CEC Version                : 2.0
>         Vendor ID                  : 0x000c03 (HDMI)
>         OSD Name                   : 'Playback'
>         Logical Addresses          : 1 (Allow RC Passthrough)
> 
>           Logical Address          : 4 (Playback Device 1)
>             Primary Device Type    : Playback
>             Logical Address Type   : Playback
>             All Device Types       : Playback
>             RC TV Profile          : None
>             Device Features        :
>                 None
> 
> $ cec-compliance
> Driver Info:
>         Driver Name                : cec-gpio
>         Adapter Name               : cec-gpio
>         Capabilities               : 0x000000af
>                 Physical Address
>                 Logical Addresses
>                 Transmit
>                 Passthrough
>                 Monitor All
>                 Monitor Pin
>         Driver version             : 5.19.0
>         Available Logical Addresses: 4
>         Connector Info             : None
>         Physical Address           : 1.0.0.0
>         Logical Address Mask       : 0x0010
>         CEC Version                : 2.0
>         Vendor ID                  : 0x000c03 (HDMI)
>         OSD Name                   : 'Playback'
>         Logical Addresses          : 1 (Allow RC Passthrough)
> 
>           Logical Address          : 4 (Playback Device 1)
>             Primary Device Type    : Playback
>             Logical Address Type   : Playback
>             All Device Types       : Playback
>             RC TV Profile          : None
>             Device Features        :
>                 None
> 
> Compliance test for cec-gpio device /dev/cec0:
> 
>     The test results mean the following:
>         OK                    Supported correctly by the device.
>         OK (Not Supported)    Not supported and not mandatory for the device.
>         OK (Presumed)         Presumably supported.  Manually check to confirm.
>         OK (Unexpected)       Supported correctly but is not expected to be supported for this device.
>         OK (Refused)          Supported by the device, but was refused.
>         OK (Expected Failure) Failed but this was expected (see -e option).
>         FAIL                  Failed and was expected to be supported by this device.
> 
> Find remote devices:
>         Polling: OK
> 
> FAIL: No remote devices found, exiting.

Yes, that looks fine.

Regards,

	Hans
diff mbox series

Patch

diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 75e7aceecac0a..f4cadbf30c6b8 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -149,7 +149,7 @@  static int gpio_set_irq_type(struct irq_data *d, u32 type)
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mxc_gpio_port *port = gc->private;
 	unsigned long flags;
-	u32 bit, val;
+	u32 bit, val, dir;
 	u32 gpio_idx = d->hwirq;
 	int edge;
 	void __iomem *reg = port->base;
@@ -208,6 +208,10 @@  static int gpio_set_irq_type(struct irq_data *d, u32 type)
 
 	writel(1 << gpio_idx, port->base + GPIO_ISR);
 
+	dir = readl(port->base + GPIO_GDIR);
+	dir &= ~BIT(gpio_idx);
+	writel(dir, port->base + GPIO_GDIR);
+
 	spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
 
 	return 0;