Skip to content
  • Benjamin Tissoires's avatar
    gpiolib-acpi: make sure we trigger edge events at least once on boot · ca876c74
    Benjamin Tissoires authored
    
    
    On some systems using edge triggered ACPI Event Interrupts, the initial
    state at boot is not setup by the firmware, instead relying on the edge
    irq event handler running at least once to setup the initial state.
    
    2 known examples of this are:
    
    1) The Surface 3 has its _LID state controlled by an ACPI operation region
     triggered by a GPIO event:
    
     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
     }
    
     Currently, the state of LIDB is wrong until the user actually closes or
     open the cover. We need to trigger the GPIO event once to update the
     internal ACPI state.
    
     Coincidentally, this also enables the Surface 2 integrated HID sensor hub
     which also requires an ACPI gpio operation region to start initialization.
    
    2) Various Bay Trail based tablets come with an external USB mux and
     TI T1210B USB phy to enable USB gadget mode. The mux is controlled by a
     GPIO which is controlled by an edge triggered ACPI Event Interrupt which
     monitors the micro-USB ID pin.
    
     When the tablet is connected to a PC (or no cable is plugged in), the ID
     pin is high and the tablet should be in gadget mode. But the GPIO
     controlling the mux is initialized by the firmware so that the USB data
     lines are muxed to the host controller.
    
     This means that if the user wants to use gadget mode, the user needs to
     first plug in a host-cable to force the ID pin low and then unplug it
     and connect the tablet to a PC, to get the ACPI event handler to run and
     switch the mux to device mode,
    
    This commit fixes both by running the event-handler once on boot.
    
    Note that the running of the event-handler is done from a late_initcall,
    this is done because the handler AML code may rely on OperationRegions
    registered by other builtin drivers. This avoids errors like these:
    
    [    0.133026] ACPI Error: No handler for Region [XSCG] ((____ptrval____)) [GenericSerialBus] (20180531/evregion-132)
    [    0.133036] ACPI Error: Region GenericSerialBus (ID=9) has no handler (20180531/exfldio-265)
    [    0.133046] ACPI Error: Method parse/execution failed \_SB.GPO2._E12, AE_NOT_EXIST (20180531/psparse-516)
    
    Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
    [hdegoede: Document BYT USB mux reliance on initial trigger]
    [hdegoede: Run event handler from a late_initcall, rather then immediately]
    Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
    Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    ca876c74