Received: by 2002:a05:6a10:9afc:0:0:0:0 with SMTP id t28csp1754424pxm; Thu, 24 Feb 2022 08:45:54 -0800 (PST) X-Google-Smtp-Source: ABdhPJzcSTgXvjAftbi7pqbTnrpU2bjOFG5xv4nSr2xgXZf/Ef1rsGcgL4y8L9OfUuGBNItWr+DH X-Received: by 2002:a63:921a:0:b0:373:df77:ee5d with SMTP id o26-20020a63921a000000b00373df77ee5dmr2907001pgd.90.1645721154675; Thu, 24 Feb 2022 08:45:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1645721154; cv=none; d=google.com; s=arc-20160816; b=ECETlRdTYshzwTT3bdUntREOOGt3fdc/T0z/YG6gBeyRLrEaQROjAnbPFB49aQD9Hz 5DoR1RH+RSQutQ2YOAoydC90opZA0+/s69LZkdirANQ61eZB8C3D9rkqcXqHO4Yej7oI W6yi4Al8lG98cVM/vix3c5t5mPJXyCMDdnrVA539oK95R1K0tDbKlS62kI2xCXvAHZQ/ 37M3/UiWKE/H7TdaNMnblPwa687GWrSy01M32HHPpId7KKR5hyQwwHzPlh4KJJOE4gLC rZalZUtRfso2mucu2SOsgSMsNz/fDeFuMW2InyOrfnryCCxSFitEVCCYibQGFYh6slmI XaTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=H2eMkw48G2IEnPpAZYbRz1ozQ55FXZI5S0Cuz1HtPj4=; b=mKU/+49mkk1blCQRnOYDVZn/fdd/XzoOdvt1E4BIW/v7RrOwvqAXVRy+Q9CAoxr492 7STSiJSrPmrSYe0lPgfxVxr+RoOsbhfb4l6HrMAK7NIsiwxrZ70RMj7PzyLbPwWS2Azq hfZ1XuiyBIJPkfPT/+LxUcbkQ/yIcoQp9iSDkiGn/7Cw1VR0qsxWzNd7rH2WnHgevN5/ VxS1Gj6njNZfnyLlJcc/olTpD0PLPwjPbMgX991ljbjMHIs1JibMLLifwij+NpWAqX8f I6Ls9QUEsf5QvX2mTlBsp9D75FeMj/HNtv7eugPtjdjcFdXzmEt3a38GwSKW2VDrfzc4 iOOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@walle.cc header.s=mail2016061301 header.b=GCZJy+ix; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id v18si2968951pfu.27.2022.02.24.08.45.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Feb 2022 08:45:54 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@walle.cc header.s=mail2016061301 header.b=GCZJy+ix; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1EFC21E1135; Thu, 24 Feb 2022 08:25:13 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229711AbiBXQSQ (ORCPT + 99 others); Thu, 24 Feb 2022 11:18:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37316 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229876AbiBXQSJ (ORCPT ); Thu, 24 Feb 2022 11:18:09 -0500 Received: from ssl.serverraum.org (ssl.serverraum.org [IPv6:2a01:4f8:151:8464::1:2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C07181B3A75; Thu, 24 Feb 2022 08:17:35 -0800 (PST) Received: from mwalle01.kontron.local. (unknown [213.135.10.150]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by ssl.serverraum.org (Postfix) with ESMTPSA id 3811B223F6; Thu, 24 Feb 2022 17:10:39 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=walle.cc; s=mail2016061301; t=1645719039; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H2eMkw48G2IEnPpAZYbRz1ozQ55FXZI5S0Cuz1HtPj4=; b=GCZJy+ixU/kQqEaic+jy/Y9fxRXjENytHV1qZM6uYGHjx5itI9KLWTyEPccFDlM99paT6j bCO2xHKvPz1Qk3mrUit4WXtxgmqOmba5ZW0ezShWKfuIvH3I0ZhG/Tuf2crXzHRsqcF4Qi hMNLtcxHAHNH5PMqv+NiTxdQVW9mdHc= From: Michael Walle To: Lars Povlsen , Steen Hegelund , Linus Walleij Cc: UNGLinuxDriver@microchip.com, linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Colin Foster , Michael Walle Subject: [PATCH v1 5/5] pinctrl: microchip-sgpio: wait until output is actually set Date: Thu, 24 Feb 2022 17:10:21 +0100 Message-Id: <20220224161021.2197263-6-michael@walle.cc> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220224161021.2197263-1-michael@walle.cc> References: <20220224161021.2197263-1-michael@walle.cc> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Right now, when a gpio value is set, the actual hardware pin gets set asynchronously. When linux write the output register, it takes some time until it is actually propagated to the output shift registers. If that output port is connected to an I2C mux for example, the linux driver assumes the I2C bus is already switched although it is not. Fortunately, there is a single shot mode with a feedback: you can trigger the single shot and the hardware will clear that bit once it has finished the clocking and strobed the load signal of the shift registers. This can take a considerable amount of time though. Measuremens have shown that it takes up to a whole burst cycle gap which is about 50ms on the largest setting. Therefore, we have to mark the output bank as sleepable. To avoid unnecessary waiting, just trigger the single shot if the value was actually changed. Signed-off-by: Michael Walle --- drivers/pinctrl/pinctrl-microchip-sgpio.c | 58 ++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index 3f3b8c482f3a..768b69929c99 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -69,6 +69,7 @@ struct sgpio_properties { #define SGPIO_OCELOT_BIT_SOURCE GENMASK(23, 12) #define SGPIO_SPARX5_AUTO_REPEAT BIT(6) +#define SGPIO_SPARX5_SINGLE_SHOT BIT(7) #define SGPIO_SPARX5_PORT_WIDTH GENMASK(4, 3) #define SGPIO_SPARX5_CLK_FREQ GENMASK(19, 8) #define SGPIO_SPARX5_BIT_SOURCE GENMASK(23, 12) @@ -118,6 +119,8 @@ struct sgpio_priv { struct regmap *regs; const struct sgpio_properties *properties; spinlock_t lock; + /* protects the config register and single shot mode */ + struct mutex poll_lock; }; struct sgpio_port_addr { @@ -225,12 +228,54 @@ static inline void sgpio_configure_clock(struct sgpio_priv *priv, u32 clkfrq) sgpio_clrsetbits(priv, REG_SIO_CLOCK, 0, clr, set); } +static int sgpio_single_shot(struct sgpio_priv *priv) +{ + u32 addr = sgpio_get_addr(priv, REG_SIO_CONFIG, 0); + int ret, ret2; + u32 ctrl; + + /* Only supported on SparX-5 for now. */ + if (priv->properties->arch != SGPIO_ARCH_SPARX5) + return 0; + + /* + * Trigger immediate burst. This only works when auto repeat is turned + * off. Otherwise, the single shot bit will never be cleared by the + * hardware. Measurements showed that an update might take as long as + * the burst gap. On a LAN9668 this is about 50ms for the largest + * setting. + * After the manual burst, reenable the auto repeat mode again. + */ + mutex_lock(&priv->poll_lock); + ret = regmap_update_bits(priv->regs, addr, + SGPIO_SPARX5_SINGLE_SHOT | SGPIO_SPARX5_AUTO_REPEAT, + SGPIO_SPARX5_SINGLE_SHOT); + if (ret) + goto out; + + ret = regmap_read_poll_timeout(priv->regs, addr, ctrl, + !(ctrl & SGPIO_SPARX5_SINGLE_SHOT), + 100, 60000); + + /* reenable auto repeat mode even if there was an error */ + ret2 = regmap_update_bits(priv->regs, addr, + SGPIO_SPARX5_AUTO_REPEAT, + SGPIO_SPARX5_AUTO_REPEAT); +out: + mutex_unlock(&priv->poll_lock); + + return ret ?: ret2; +} + static int sgpio_output_set(struct sgpio_priv *priv, struct sgpio_port_addr *addr, int value) { unsigned int bit = SGPIO_SRC_BITS * addr->bit; + u32 reg = sgpio_get_addr(priv, REG_PORT_CONFIG, addr->port); + bool changed; u32 clr, set; + int ret; switch (priv->properties->arch) { case SGPIO_ARCH_LUTON: @@ -249,7 +294,16 @@ static int sgpio_output_set(struct sgpio_priv *priv, return -EINVAL; } - sgpio_clrsetbits(priv, REG_PORT_CONFIG, addr->port, clr, set); + ret = regmap_update_bits_check(priv->regs, reg, clr | set, set, + &changed); + if (ret) + return ret; + + if (changed) { + ret = sgpio_single_shot(priv); + if (ret) + return ret; + } return 0; } @@ -788,6 +842,7 @@ static int microchip_sgpio_register_bank(struct device *dev, gc->of_gpio_n_cells = 3; gc->base = -1; gc->ngpio = ngpios; + gc->can_sleep = !bank->is_input; if (bank->is_input && priv->properties->flags & SGPIO_FLAGS_HAS_IRQ) { int irq = fwnode_irq_get(fwnode, 0); @@ -848,6 +903,7 @@ static int microchip_sgpio_probe(struct platform_device *pdev) priv->dev = dev; spin_lock_init(&priv->lock); + mutex_init(&priv->poll_lock); reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch"); if (IS_ERR(reset)) -- 2.30.2