From mboxrd@z Thu Jan 1 00:00:00 1970 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 79927CEF14D for ; Tue, 8 Oct 2024 10:37:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=hk/cnPLhu0UgkHduMRy01DxcYt4eJaBLwDUFI+yCrVI=; b=3s+0L1VVHq/5wM3Alha7I+C/y4 FxQNzVxnd/PiUC9Ov5H09O1t0BaGPp26nfLfR5IHh3YimehP2uM5vLdiw2K10C+C77sWhOqclOEnP mr3UXA//HoDjLpDTqII5fekpdQEifOllyDvHcJJZq+lTHsv+satmSCl1E7/2sMjPnQCb//ecbaa2F I4cpNb0VwAp8pO/qWzNF1uDC8Q/Bu2tNspX1xBLki0bsG0MSVgyBzRDVRHEyZlJHsjNsjdXKh2Q3Q Fv8Jj/C5YLFW7FuuwM6mNzfGcCb2Ikt15mNbH46rJ2A1Nmg2dN/2sGVynVY++EOtPXn4XoFMJENap Mqw01WCQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1sy7au-00000005TkF-15a8; Tue, 08 Oct 2024 10:37:32 +0000 Received: from relay4-d.mail.gandi.net ([2001:4b98:dc4:8::224]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1sy7TQ-00000005Sas-0pMK for linux-arm-kernel@lists.infradead.org; Tue, 08 Oct 2024 10:29:51 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 97BC6E000F; Tue, 8 Oct 2024 10:29:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1728383385; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hk/cnPLhu0UgkHduMRy01DxcYt4eJaBLwDUFI+yCrVI=; b=FQ20dmegjSaQ0cuGROfvuBqxrPgvwwm998u4x+bVCjBMgeqNYmJnkSiNB5AHzWRJ5P3l5v hIZ3ZAfjPUbgOgo3pPuNUsNFejFjXrMu2e3/9Uqa3vEwpCwP/qqDhwm09GGv/HSd4QMx41 enUmKl1d3JAhTQAp5MPH/XNj+rxWXEijbb+lBuwajx87d7N1K4P87q/BuGIPtCFJCRApUq qTfe4Y5nUy6QU+8Mfq+DY2TVJA2rwAlHiDZiYEaymf8FSQWOPyh4SWjLYzAPTP3I5BXpKW 87kOhmghC+M1gfbAprfzj5kph1ctzGChnTzU/MzZn07MaQqfcl7Z6zdjvcFJ0A== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Tue, 08 Oct 2024 12:29:42 +0200 Subject: [PATCH 3/4] i2c: nomadik: fix BRCR computation MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20241008-mbly-i2c-v1-3-a06c1317a2f7@bootlin.com> References: <20241008-mbly-i2c-v1-0-a06c1317a2f7@bootlin.com> In-Reply-To: <20241008-mbly-i2c-v1-0-a06c1317a2f7@bootlin.com> To: Linus Walleij , Andi Shyti , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Vladimir Kondratiev , =?utf-8?q?Gr=C3=A9gory_Clement?= , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.14.2 X-GND-Sasl: theo.lebrun@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241008_032948_557785_2179FE64 X-CRM114-Status: GOOD ( 12.83 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Current BRCR computation is: brcr = floor(i2cclk / (clkfreq * div)) With brcr: "baud rate counter", an internal clock divider, and i2cclk: input clock rate (24MHz, 38.4MHz or 48MHz), and clkfreq: desired bus rate, and div: speed-mode dependent divider (2 for standard, 3 otherwise). Assume i2cclk=48MHz, clkfreq=3.4MHz, div=3, then brcr = floor(48MHz / (3.4MHz * 3)) = 4 and resulting bus rate = 48MHz / (4 * 3) = 4MHz Assume i2cclk=38.4MHz, clkfreq=1.0MHz, div=3, then brcr = floor(38.4MHz / (1.0MHz * 3)) = 12 and resulting bus rate = 38.4MHz / (12 * 3) = 1066kHz The current computation means we always pick the smallest divider that gives a bus rate above target. We should instead pick the largest divider that gives a bus rate below target, using: brcr = floor(i2cclk / (clkfreq * div)) + 1 If we redo the above examples: Assume i2cclk=48MHz, clkfreq=3.4MHz, div=3, then brcr = floor(48MHz / (3.4MHz * 3)) + 1 = 5 and resulting bus rate = 48MHz / (5 * 3) = 3.2MHz Assume i2cclk=38.4MHz, clkfreq=1.0MHz, div=3, then brcr = floor(38.4MHz / (1.0MHz * 3)) + 1 = 13 and resulting bus rate = 38.4MHz / (13 * 3) = 985kHz This is much less of an issue with slower bus rates (ie those currently supported), because the gap from one divider to the next is much smaller. It however keeps us from always using bus rates superior to the target. This fix is required for later on supporting faster bus rates: I2C_FREQ_MODE_FAST_PLUS (1MHz) and I2C_FREQ_MODE_HIGH_SPEED (3.4MHz). Signed-off-by: Théo Lebrun --- drivers/i2c/busses/i2c-nomadik.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index ea511d3a58073eaedb63850026e05b59427a69c6..68ce39352d67477fa22424e2dc0f8d1741498cd1 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -453,9 +453,12 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv) * operation, and the other is for std, fast mode, fast mode * plus operation. Currently we do not supprt high speed mode * so set brcr1 to 0. + * + * BRCR is a clock divider amount. Pick highest value that + * leads to rate strictly below target. */ brcr1 = FIELD_PREP(I2C_BRCR_BRCNT1, 0); - brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, i2c_clk / (priv->clk_freq * div)); + brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, i2c_clk / (priv->clk_freq * div) + 1); /* set the baud rate counter register */ writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR); -- 2.46.2