From patchwork Fri Jul 6 09:32:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 940356 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FYUfw8a2"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41MTzD17Bgz9s1B for ; Fri, 6 Jul 2018 19:32:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753638AbeGFJcj (ORCPT ); Fri, 6 Jul 2018 05:32:39 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:55783 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753632AbeGFJci (ORCPT ); Fri, 6 Jul 2018 05:32:38 -0400 Received: by mail-wm0-f68.google.com with SMTP id v16-v6so14229051wmv.5 for ; Fri, 06 Jul 2018 02:32:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=m9PF4+EOnybL1IroZ40IEYpqtSnY0aKQBZ8vb/ys/Ik=; b=FYUfw8a29TJHb0pZ6H/rqlOpoa0XGfKZ9JP2/IterdR7WhEkA6JXoadBvg7KygyXdR vsy9jvRm8iLN0wUKCSNQRyUruOpq3XT0UHQDMeNyGAFj3eh58YJZiFiqkcdnTRk7Co0e F6ztiiyTW8G6oEf2uGIAcjFvNC8JMY5zdG67hxIysQWfSwiOoMqZT8Iu3Ie80xbAu3qR 5ywoHWahehNiZYCa99/gMDmNSF5Lpf6zflHsLlFSnE6lmBy5GwljFXv6vV//o4VSV8xB vGyBbJIQD65xjLJs8Nm2aI2CpKJmNOyJ+z2LAxXAskkKUmT5CqzHDsI/EcNHCSW6d3AE ejTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=m9PF4+EOnybL1IroZ40IEYpqtSnY0aKQBZ8vb/ys/Ik=; b=kfag7ah7Ts5uSlHDcMcF6RppCBAItsYEG1hxbqo4Yu2jBqsiw6AOW2rVvA2hk7OjLZ hpfyMNd/uwp/dgr/fIDIgwFlP5pYXaISEkeTA/il9ZOEH3aQzJxEbGt/EtvScS6gW9PL J0VSls3XYoggjZBfNWAuSPR4eW6yI6I7rU2qQd6k6dLNW3CcTPJRvDF18xgQmbrMTFjk oxB0RM0FGhDQLKaYEgB3jFodyDE1YkrudB2QFVnnW4wRdAW6PbTeJdNavh3wFWOT8EaZ l+WGR7xGUXpd2oTRCuBuuL1khvroVxODourJY+or9SFFX+hsTjVif0JVC4T6Q1K85PL4 BqaQ== X-Gm-Message-State: APt69E3RZ6HIhu17OFxf2+0d747oscz1z9cRRsaCESqn7JSJ9jyax8Sa YS55tHdzk8dJ3426xQJSDjc= X-Google-Smtp-Source: AAOMgpekgDn10hRXeTrKepILy/jeQbbKQ1buHFH1ZAEHCOTvYQbbNTEnIvyBx3amgvgGz33VMgsBqw== X-Received: by 2002:a1c:864c:: with SMTP id i73-v6mr6514636wmd.40.1530869557147; Fri, 06 Jul 2018 02:32:37 -0700 (PDT) Received: from localhost.localdomain.es (nat-wifi-invi.ual.es. [150.214.223.90]) by smtp.gmail.com with ESMTPSA id f138-v6sm7027378wmd.13.2018.07.06.02.32.35 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 06 Jul 2018 02:32:36 -0700 (PDT) From: Hans de Goede X-Google-Original-From: Hans de Goede To: Mika Westerberg , Heikki Krogerus , Linus Walleij Cc: Hans de Goede , Benjamin Tissoires , Andy Shevchenko , linux-gpio@vger.kernel.org Subject: [RFC] gpiolib-acpi: make sure we trigger edge events at least once on boot Date: Fri, 6 Jul 2018 11:32:29 +0200 Message-Id: <20180706093229.19072-2-hdegoede@redhat.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180706093229.19072-1-hdegoede@redhat.com> References: <20180706093229.19072-1-hdegoede@redhat.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Benjamin Tissoires 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. Signed-off-by: Benjamin Tissoires [hdegoede: Document BYT USB mux reliance on initial trigger] Signed-off-by: Hans de Goede --- drivers/gpio/gpiolib-acpi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index e2232cbcec8b..7749b2ff7367 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -136,7 +136,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, irq_handler_t handler = NULL; struct gpio_desc *desc; unsigned long irqflags; - int ret, pin, irq; + int ret, pin, irq, value; if (!acpi_gpio_get_irq_resource(ares, &agpio)) return AE_OK; @@ -167,6 +167,8 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, gpiod_direction_input(desc); + value = gpiod_get_value(desc); + ret = gpiochip_lock_as_irq(chip, pin); if (ret) { dev_err(chip->parent, "Failed to lock GPIO as interrupt\n"); @@ -222,6 +224,15 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, enable_irq_wake(irq); list_add_tail(&event->node, &acpi_gpio->events); + + /* + * Make sure we trigger the initial state of the IRQ when + * using RISING or FALLING. + */ + if (((irqflags & IRQF_TRIGGER_RISING) && value == 1) || + ((irqflags & IRQF_TRIGGER_FALLING) && value == 0)) + handler(-1, event); + return AE_OK; fail_free_event: