From patchwork Mon Aug 7 21:45:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hugo Villeneuve X-Patchwork-Id: 711877 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB84DC07E8D for ; Mon, 7 Aug 2023 21:46:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230405AbjHGVqY (ORCPT ); Mon, 7 Aug 2023 17:46:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34010 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230021AbjHGVqW (ORCPT ); Mon, 7 Aug 2023 17:46:22 -0400 Received: from mail.hugovil.com (mail.hugovil.com [162.243.120.170]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E5911722; Mon, 7 Aug 2023 14:46:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=hugovil.com ; s=x; h=Subject:Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Cc:To :From:subject:date:message-id:reply-to; bh=enU4NC1XhRMNQEPd0as2RRvEtsGncqBf+Slh5pDF7Rg=; b=iBJ/WxPRm9CXh18Q97WivGhLfR uU3l7LuTesZ64AKYxIQ2NZywC4Hz39jvk8Av9gWzeVUbXkT892fk5ytiwE5VXvrcxqrBgrNQFS6Fo 5PJw/cZqqEro6ZoG/kROGWhZKehydCoNINnMoNKlmR/nb66xlNp3uISbVeZn3zS/WOGA=; Received: from modemcable061.19-161-184.mc.videotron.ca ([184.161.19.61]:47088 helo=localhost.localdomain) by mail.hugovil.com with esmtpa (Exim 4.92) (envelope-from ) id 1qT83L-0000hD-JU; Mon, 07 Aug 2023 17:46:16 -0400 From: Hugo Villeneuve To: gregkh@linuxfoundation.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, jirislaby@kernel.org, jringle@gridpoint.com, tomasz.mon@camlingroup.com, l.perczak@camlintechnologies.com Cc: linux-serial@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, hugo@hugovil.com, linux-gpio@vger.kernel.org, Hugo Villeneuve , stable@vger.kernel.org, Lech Perczak Date: Mon, 7 Aug 2023 17:45:55 -0400 Message-Id: <20230807214556.540627-6-hugo@hugovil.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230807214556.540627-1-hugo@hugovil.com> References: <20230807214556.540627-1-hugo@hugovil.com> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 184.161.19.61 X-SA-Exim-Mail-From: hugo@hugovil.com Subject: [PATCH v10 5/6] serial: sc16is7xx: fix bug when first setting GPIO direction X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.hugovil.com) Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org From: Hugo Villeneuve When configuring a pin as an output pin with a value of logic 0, we end up as having a value of logic 1 on the output pin. Setting a logic 0 a second time (or more) after that will correctly output a logic 0 on the output pin. By default, all GPIO pins are configured as inputs. When we enter sc16is7xx_gpio_direction_output() for the first time, we first set the desired value in IOSTATE, and then we configure the pin as an output. The datasheet states that writing to IOSTATE register will trigger a transfer of the value to the I/O pin configured as output, so if the pin is configured as an input, nothing will be transferred. Therefore, set the direction first in IODIR, and then set the desired value in IOSTATE. This is what is done in NXP application note AN10587. Fixes: dfeae619d781 ("serial: sc16is7xx") Cc: Signed-off-by: Hugo Villeneuve Reviewed-by: Lech Perczak Tested-by: Lech Perczak --- drivers/tty/serial/sc16is7xx.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index b45e34e3910d..cfc88959b2f7 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1342,9 +1342,18 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, state |= BIT(offset); else state &= ~BIT(offset); - sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state); + + /* + * If we write IOSTATE first, and then IODIR, the output value is not + * transferred to the corresponding I/O pin. + * The datasheet states that each register bit will be transferred to + * the corresponding I/O pin programmed as output when writing to + * IOSTATE. Therefore, configure direction first with IODIR, and then + * set value after with IOSTATE. + */ sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset), BIT(offset)); + sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state); return 0; }