• Mika Westerberg's avatar
    gpio / ACPI: Allow shared GPIO event to be read via operation region · c103a10f
    Mika Westerberg authored
    In Microsoft Surface3 the GPIO detecting lid state is shared between GPIO
    event and operation region. Below is simplied version of the DSDT from
    Surface3 including relevant parts:
    
        Scope (GPO0)
        {
            Name (_AEI, ResourceTemplate ()
            {
                GpioInt (Edge, ActiveBoth, Shared, PullNone, 0x0000,
                    "\\_SB.GPO0", 0x00, ResourceConsumer, ,
                    )
                    {   // Pin list
                        0x004C
                    }
            })
    
            OperationRegion (GPOR, GeneralPurposeIo, Zero, One)
            Field (GPOR, ByteAcc, NoLock, Preserve)
            {
                Connection (
                    GpioIo (Shared, PullNone, 0x0000, 0x0000,
                        IoRestrictionNone, "\\_SB.GPO0", 0x00,
                        ResourceConsumer,,)
                        {   // Pin list
                            0x004C
                        }
                ),
                HELD,   1
            }
    
            Method (_E4C, 0, Serialized)  // _Exx: Edge-Triggered GPE
            {
                If ((HELD == One))
                {
                    ^^LID.LIDB = One
                }
                Else
                {
                    ^^LID.LIDB = Zero
                    Notify (LID, 0x80) // Status Change
                }
    
                Notify (^^PCI0.SPI1.NTRG, One) // Device Check
            }
        }
    
    When GPIO 0x4c changes we call ASL method _E4C which tries to read HELD
    field (the same GPIO). This triggers following error on the console:
    
        ACPI Error: Method parse/execution failed [\_SB.GPO0._E4C]
            (Node ffff88013f4b4438), AE_ERROR (20150930/psparse-542)
    
    The error happens because ACPI GPIO operation region handler
    (acpi_gpio_adr_space_handler()) tries to acquire the very same GPIO which
    returns an error (-EBUSY) because the GPIO is already reserved for the GPIO
    event.
    
    Fix this so that we "borrow" the event GPIO if we find the GPIO belongs to
    an event. Allow this only for GPIOs that are read.
    
    To be able to go through acpi_gpio->events list for operation region access
    we need to make sure the list is properly initialized whenever GPIO chip is
    registered.
    
    Link: https://bugzilla.kernel.org/show_bug.cgi?id=106571Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    c103a10f
gpiolib-acpi.c 21.2 KB