From patchwork Sat Jun 10 06:15:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sam Edwards X-Patchwork-Id: 1793272 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=85.214.62.61; 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=ls+v6lMe; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QdSNw1w7xz20Vx for ; Sat, 10 Jun 2023 16:15:26 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F3D82846E5; Sat, 10 Jun 2023 08:15:16 +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="ls+v6lMe"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D5D9D846D8; Sat, 10 Jun 2023 08:15:14 +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=unavailable autolearn_force=no version=3.4.2 Received: from mail-il1-x12b.google.com (mail-il1-x12b.google.com [IPv6:2607:f8b0:4864:20::12b]) (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 66709846E5 for ; Sat, 10 Jun 2023 08:15:11 +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-x12b.google.com with SMTP id e9e14a558f8ab-33e5054ba6fso11460335ab.0 for ; Fri, 09 Jun 2023 23:15:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686377709; x=1688969709; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=gOvdBFkRLK209q7BLB7c0MdHdGbeky62jt3U/Pmg0f0=; b=ls+v6lMeArPMfQCW+tLLFoyK9I2ubiUoE5Ws+LVFkl6LhTEdEo88cTgbeZI0JgSvjP lzg9BOjuPU74I3DGl+PlAm+3C6kVt4aaO6eZB32OZG1ic3TcXWKshvCLP2hmf+SrMcPw VSe6beQxWRiWQ/8iFuhCXkkUiV8MW1P2724xAwIsun1BsR7a+3Fk/xbeDYltGlhX6Z3t 41guKHTo4qFhLVVJSkEx4dnsNXYlxzr18hqipPBzPlfD8J1B7Tpk2SH0j8uAUC/JvMJP LZYEBT6yjjyEaeAJ5EqFXdRLS9IP9svd0T53r2uK18MmFY6ErWZ60xOLR8/JjbyA0VeN x2pQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686377709; x=1688969709; 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=gOvdBFkRLK209q7BLB7c0MdHdGbeky62jt3U/Pmg0f0=; b=f20onUPPzW8K+ckhrcazINisQdKFggOm+/3WoilvnVwx959p/UiaDOwp1rEjmhy723 bFAaYCDA0/1FtXfQ3owCRbcvhWTrPFaip3j2CXJyE7QTBvvYx0+VMw4m6Y/d/yHyrNQe KOFW20JjjUWRKoHsb5F6fdFp1l68i635RDph6rQFrnlDOrB3NqFC39mYBf2dtDl2DmAl 9kmplk3i5zGSXcl6ILajYUw0QIP4lOvJj7t72xPTN8JsmfjY/UVE6x8M7Dzv3E3BcEBM CD8iS45SK3csvoz935beri3ceDG0IA4n4owldp5nbYlsk5pYvPCLvkH6UgtUy34C+4+Z mLEQ== X-Gm-Message-State: AC+VfDyD4i8OEOA1LzxPOUpHdSQmHfn9aEcmIpm9W91XhbznjLCCXOnq Nm8F8aN8XN40tGIeEVmAlscopPfaMwnp/luy X-Google-Smtp-Source: ACHHUZ6Ztt6KdwTjjrOD4Xrdc8YGgwzcWvC48Zi2wIzA8M9BiGSmq+mqXhEvWifcRvBosMSWqFZ3Uw== X-Received: by 2002:a92:d64a:0:b0:33b:ef57:65b1 with SMTP id x10-20020a92d64a000000b0033bef5765b1mr2155698ilp.19.1686377709395; Fri, 09 Jun 2023 23:15:09 -0700 (PDT) Received: from celestia.nettie.lan ([2001:470:42c4:101:d264:8856:b4e9:a431]) by smtp.gmail.com with ESMTPSA id o16-20020a92c050000000b003339733e374sm1495387ilf.86.2023.06.09.23.15.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Jun 2023 23:15:08 -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: [RFC PATCH] i2c: mvtwsi: reinitialize controller to clear bus errors Date: Sat, 10 Jun 2023 00:15:00 -0600 Message-Id: <20230610061500.119123-1-CFSworks@gmail.com> X-Mailer: git-send-email 2.39.2 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 Hi I²C maintainers, My target has the following devices sharing one bus: - 24C02 EEPROM - Realtek 8370 Ethernet switch - Allwinner T113-s3 (running U-Boot, interfacing via MVTWSI) The RTL8370 is configured in "EEPROM autoload" mode, so on reset it will load the full contents of the EEPROM. During this sequence, it does an odd move where it sends a re-start, stop, pulses scl low, and then a fresh start. Something about this sequence (I'm betting the scl pulse after stop) upsets the MVTWSI controller, causing it to retreat into state 0x00, which the documentation for my chip names "bus error." I'd guess this is a feature for slave operation: in slave mode, the controller FSM is completely at the mercy of the bus, and so a misbehaving/glitching bus can result in essentially a random walk through the states. Rather than allow that (and risk a potentially dangerous accidental write), the controller goes to a failsafe "bus error" state and remains there, effectively shutting down the whole controller. However, in master mode (which U-Boot uses exclusively), this feature is a nuisance. We do not care what another master was doing on the bus previously, as long as it is in the proper idle state when we want to use it. We also don't care if the bus error was our fault in a previous transaction, since the error would have been reported at that time. I reckon that it makes sense to check for this "bus error" state at the beginning of each new read/write and clear it if detected. Unfortunately, I couldn't find any way to coax the FSM out of the error state just by poking at the control register. It's possible I didn't look hard enough (I'm willing to try other things), but I'm otherwise left with only the obvious way out: a reset. Since that also resets the baud and address registers, I have to save and restore those too. Attached here is my RFC patch (which DOES resolve my problem), for feedback and suggestions on what I might try differently, as I'm not sure whether or not I like this approach: - I would be happier if the code did a fresh init instead of saving and restoring register state, but this driver is plumbed in a way that the config struct isn't readily accessible at the low level. - I don't really like having to duplicate the state check in the read and write functions; is there anything I can do that's more DRY? - Avoiding a reset would be nice, ideally avoiding the "bus error" state altogether by disabling the error detection somehow. Thoughts? Cheers, Sam --- drivers/i2c/mvtwsi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index d088ea75b9..38a3bdade0 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);