From patchwork Tue Jul 25 22:13:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Edwards X-Patchwork-Id: 1812901 X-Patchwork-Delegate: hs@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20221208 header.b=shpmpmeb; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R9WWx2kmwz1yY5 for ; Wed, 26 Jul 2023 08:13:49 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3377086789; Wed, 26 Jul 2023 00:13:39 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="shpmpmeb"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 132C586813; Wed, 26 Jul 2023 00:13:36 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 172FC86789 for ; Wed, 26 Jul 2023 00:13:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=cfsworks@gmail.com Received: by mail-il1-x12d.google.com with SMTP id e9e14a558f8ab-348dfefd1a4so6070795ab.1 for ; Tue, 25 Jul 2023 15:13:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1690323211; x=1690928011; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=mmELVcIJ+TytuW/IF8gF5KehUI30vdADm8CbeyCXmYY=; b=shpmpmebb2yuAoaWnhstF1AfoH00YvFOn3WpjrYFFhzxOEdTq6ONrv567eaIiQ0nC+ NFBzMvDsy3n+JxOvorZfK37QabOU8dno6KCBbD04sREMKzYBtCUzr6BMJk3+GPPgjBJA rrMX4xPYWdB5YPsQNmhDVgdSb8CAvt/7DtYKMbYlTwg03TSKzJtZdTP16Ak+wWyUOrMU 2KpPMHIOkTsyU30RaqXAHlABsoJtFfypHIHunAGRe5YsoE16SB7npaWW9zuisT4NjLbi VnUYjSaQDQiuVdvrAlu6uBDchAAwY5JsN4k+v3KwmbZNq3INj34oTqp1vH2Q3/N6rtOY mNvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690323211; x=1690928011; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=mmELVcIJ+TytuW/IF8gF5KehUI30vdADm8CbeyCXmYY=; b=ahQc2H0FQYXKA7RD8IdIg+Ez2XG/xQp2izE7BbRuleKYY0iYgpym0tIagqgQmhj0VM HO25LJmKBz2ZkVtRPMjm3XY44ClZSjSs3cAMsFFMrbu7rrXOqAQnaDRWQWcmj6GHCGjM 56cW/s4lv455rn9Q/DyM4RJ1zGCkm9QGcjeWGfmkXZwcQ4R+0OJpkBHEMjdmRNVVLY1B oYeJ2bp8GMICAaMsO6eQPp9Xx2qtL4VlHdwMLV9A7wi5jgfejPztC4nfAZBpqQZP+7UU /3dbvRj3hMp3kmkNklo+tYf0wlKwQ3HlT4PcSi8obs1AYWoB+9xhfA2k3WVY4int3Unn IfjQ== X-Gm-Message-State: ABy/qLbZlL6pOGwGfgbHhIl4OMEjM/lBwPpO9/5g5T5YP8cmmpkACVXv 7vSesQJGIYPuCCNrTddcuYVZHnSq4to5AA== X-Google-Smtp-Source: APBJJlFE/XQcBhXsxMylaTeplQBK11SJyW41/m6aiwySswXHZ83ryarqse52rFpMB7KA65c9xTnKuQ== X-Received: by 2002:a05:6e02:1a4f:b0:345:d58d:9ae5 with SMTP id u15-20020a056e021a4f00b00345d58d9ae5mr348756ilv.7.1690323208486; Tue, 25 Jul 2023 15:13:28 -0700 (PDT) Received: from celestia.nettie.lan ([2001:470:42c4:101:a777:7df3:b9ec:588b]) by smtp.gmail.com with ESMTPSA id g13-20020a05663811cd00b0042b72208aa6sm3733712jas.77.2023.07.25.15.13.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Jul 2023 15:13:28 -0700 (PDT) From: Sam Edwards X-Google-Original-From: Sam Edwards To: u-boot@lists.denx.de Cc: Stefan Roese , Heiko Schocher , Sam Edwards Subject: [PATCH] i2c: mvtwsi: reset controller if stuck in "bus error" state Date: Tue, 25 Jul 2023 16:13:05 -0600 Message-ID: <20230725221305.49268-1-CFSworks@gmail.com> X-Mailer: git-send-email 2.41.0 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The MVTWSI controller can act either as a master or slave device. When acting as a master, the FSM is driven by the CPU. As a slave, the FSM is driven by the bus directly. In what is (apparently) a safety mechanism, if the bus transitions our FSM in any improper way, the FSM goes to a "bus error" state (0x00). I could find no documented or experimental way to get the FSM out of this state, except for a controller reset. Since U-Boot only uses the MVTWSI controller as a bus master, this feature only gets in the way: we do not care what happened on the bus previously as long as the bus is ready for a new transaction. So, when trying to start a new transaction, check for this state and reset the controller if necessary. Note that this should not be confused with the "deblocking" technique (used by the `i2c reset` command), which involves pulsing SCL repeatedly if SDA is found to be held low, in an attempt to force the bus back to an idle state. This patch only resets the controller in case something else had previously upset it, and (in principle) results in no externally-observable change in behavior. Signed-off-by: Sam Edwards Reviewed-by: Stefan Roese Reviewed-by: Heiko Schocher --- drivers/i2c/mvtwsi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 93bbc6916e..14cdb0f663 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -142,6 +142,8 @@ enum mvtwsi_ctrl_register_fields { * code. */ enum mvstwsi_status_values { + /* Protocol violation on bus; this is a terminal state */ + MVTWSI_BUS_ERROR = 0x00, /* START condition transmitted */ MVTWSI_STATUS_START = 0x08, /* Repeated START condition transmitted */ @@ -525,6 +527,36 @@ static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed, #endif } +/* + * __twsi_i2c_reinit() - Reset and reinitialize the I2C controller. + * + * This function should be called to get the MVTWSI controller out of the + * "bus error" state. It saves and restores the baud and address registers. + * + * @twsi: The MVTWSI register structure to use. + * @tick: The duration of a clock cycle at the current I2C speed. + */ +static void __twsi_i2c_reinit(struct mvtwsi_registers *twsi, uint tick) +{ + uint baud; + uint slaveadd; + + /* Save baud, address registers */ + baud = readl(&twsi->baudrate); + slaveadd = readl(&twsi->slave_address); + + /* Reset controller */ + twsi_reset(twsi); + + /* Restore baud, address registers */ + writel(baud, &twsi->baudrate); + writel(slaveadd, &twsi->slave_address); + writel(0, &twsi->xtnd_slave_addr); + + /* Assert STOP, but don't care for the result */ + (void) twsi_stop(twsi, tick); +} + /* * i2c_begin() - Start a I2C transaction. * @@ -621,6 +653,11 @@ static int __twsi_i2c_read(struct mvtwsi_registers *twsi, uchar chip, int stop_status; int expected_start = MVTWSI_STATUS_START; + /* Check for (and clear) a bus error from a previous failed transaction + * or another master on the same bus */ + if (readl(&twsi->status) == MVTWSI_BUS_ERROR) + __twsi_i2c_reinit(twsi, tick); + if (alen > 0) { /* Begin i2c write to send the address bytes */ status = i2c_begin(twsi, expected_start, (chip << 1), tick); @@ -668,6 +705,11 @@ static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip, { int status, stop_status; + /* Check for (and clear) a bus error from a previous failed transaction + * or another master on the same bus */ + if (readl(&twsi->status) == MVTWSI_BUS_ERROR) + __twsi_i2c_reinit(twsi, tick); + /* Begin i2c write to send first the address bytes, then the * data bytes */ status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick);