Received: by 2002:a05:6358:489b:b0:bb:da1:e618 with SMTP id x27csp4949873rwn; Mon, 12 Sep 2022 01:42:54 -0700 (PDT) X-Google-Smtp-Source: AA6agR6smEqd4V7b5nsGsehgGFUeYm/z28aQkfB2PZ4X7XvXKv9p1hsmfzeLspAEYocdtyxi97YN X-Received: by 2002:a17:902:f0d4:b0:176:988a:77fd with SMTP id v20-20020a170902f0d400b00176988a77fdmr25618948pla.25.1662972174590; Mon, 12 Sep 2022 01:42:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662972174; cv=none; d=google.com; s=arc-20160816; b=bBltcWE2pxuZqdlw7NrH9Oj4/+22Jcj6YihTjLdzpDe/+tEchigskpAMAWME3NruGr whCOhH+VsFgcGSKTooEA44NkEcfFEagpGxfWk0Sa9HmW/CZcnEBZbyXOp2XktFBJWM/D bZ71J1aI4QC0FVozeoJAN7CJOcuxdwWEefoMvoCC0mbBKP6Af0NY1QDnsbnaCPOzYTiq M0bcemXj+32ye/pC3iVQ22HOk2oCTuwAStYqObbuusG1BXdH1lrceE3YkUm1vcGc7OvO 6+aQyqmy+v/PH3aYaZ//vFfOZWmFoMkUK6KIycSQPubIE0L81GmN3mBtDCMD7kOAm8XH 1w1A== 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 :message-id:date:subject:cc:to:from:dkim-signature:dkim-signature; bh=rJYhrR428jNNlRLZhs10drooq2kV+pRSFfgjK79rQ5o=; b=zLR8FD2Ab22sJA8KopqC0sWKa4GXbi4dGT6b/DzKAMisRBnU6Pn+3h8Gp1iAMBKD78 m/fDGpiAN+2y1Yzl0SXij4OKWL0tXFOTqYfPvCnwIz8GwgdP41r/JMI78pGInfbWvSOy gUv7ncnNo3+xIFdJM916SZwMWygTG8zJBUgSlHr1D0G4w4en1p0XZoMVEFWaqBWOXS+s C2/aA8zxR2hFt0DHU1pTIXK5ZNgNlg24bYfXoPOtIar275KUBNcLsNURe7CImZ859vfa 28kiBI42K9jaobDhPMYaLk6qdJWGE4fx0EkZ9JC+Y6dWDNLDhNNa6fXND6U54iZC0BYt KSNA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=2Kiou3zV; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i68-20020a626d47000000b00540e1e14574si6829109pfc.282.2022.09.12.01.42.43; Mon, 12 Sep 2022 01:42:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=2Kiou3zV; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230005AbiILIdP (ORCPT + 99 others); Mon, 12 Sep 2022 04:33:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229956AbiILIdL (ORCPT ); Mon, 12 Sep 2022 04:33:11 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E26111D0F3; Mon, 12 Sep 2022 01:33:10 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 9A8AF2274E; Mon, 12 Sep 2022 08:33:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1662971589; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=rJYhrR428jNNlRLZhs10drooq2kV+pRSFfgjK79rQ5o=; b=2Kiou3zVzuTQBhj0JOVbC5LQqp5babdNmd9lb3xhg9cgNd0CF0CjHzvEcCDCPzUDICDLKz zRDFs0jGrJs1wTPAdApqcti1a+RjEMue7nXJwFQu6exIv+EAThlLONlHCDL6bk8RJdhI9T ssxHx8Foc+AIOAYZgBPWlHqu5CNEh8I= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1662971589; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=rJYhrR428jNNlRLZhs10drooq2kV+pRSFfgjK79rQ5o=; b=bBONwScwe9pJ9UzZXwsugFYltwW9ACYr9AquEliNmC1uYMZn7pfLW1uKlK7wDWKrHaVmr8 XVOWSCFuLiJp9XBw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 812A2139E0; Mon, 12 Sep 2022 08:33:09 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id hPNUH8XuHmMyLAAAMHmgww (envelope-from ); Mon, 12 Sep 2022 08:33:09 +0000 From: "Ivan T. Ivanov" To: Michael Turquette , Stephen Boyd , Florian Fainelli , Ray Jui , Scott Branden , Broadcom internal kernel review list , Maxime Ripard , Nicolas Saenz Julienne , Stefan Wahren , "Ivan T. Ivanov" Cc: Phil Elwell , linux-clk@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v5] clk: bcm2835: Round UART input clock up Date: Mon, 12 Sep 2022 11:13:04 +0300 Message-Id: <20220912081306.24662-1-iivanov@suse.de> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham 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 It was reported that RPi3[1] and RPi Zero 2W boards have issues with the Bluetooth. It turns out that when switching from initial to operation speed host and device no longer can talk each other because host uses incorrect UART baud rate. The UART driver used in this case is amba-pl011. Original fix, see below Github link[2], was inside pl011 module, but somehow it didn't look as the right place to fix. Beside that this original rounding function is not exactly perfect for all possible clock values. So I deiced to move the hack to the platform which actually need it. The UART clock is initialised to be as close to the requested frequency as possible without exceeding it. Now that there is a clock manager that returns the actual frequencies, an expected 48MHz clock is reported as 47999625. If the requested baud rate == requested clock/16, there is no headroom and the slight reduction in actual clock rate results in failure. If increasing a clock by less than 0.1% changes it from ..999.. to ..000.., round it up. [1] https://bugzilla.suse.com/show_bug.cgi?id=1188238 [2] https://github.com/raspberrypi/linux/commit/ab3f1b39537f6d3825b8873006fbe2fc5ff057b7 Cc: Phil Elwell Signed-off-by: Ivan T. Ivanov Reviewed-by: Stefan Wahren --- drivers/clk/bcm/clk-bcm2835.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 48a1eb9f2d55..4361ec4c659a 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -502,6 +503,8 @@ struct bcm2835_clock_data { bool low_jitter; u32 tcnt_mux; + + bool round_up; }; struct bcm2835_gate_data { @@ -993,12 +996,34 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock, return temp; } +static unsigned long bcm2835_round_rate(unsigned long rate) +{ + unsigned long scaler; + unsigned long limit; + + limit = rate / 100000; + + scaler = 1; + while (scaler < limit) + scaler *= 10; + + /* + * If increasing a clock by less than 0.1% changes it + * from ..999.. to ..000.., round up. + */ + if ((rate + scaler - 1) / scaler % 1000 == 0) + rate = roundup(rate, scaler); + + return rate; +} + static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, unsigned long parent_rate) { struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct bcm2835_cprman *cprman = clock->cprman; const struct bcm2835_clock_data *data = clock->data; + unsigned long rate; u32 div; if (data->int_bits == 0 && data->frac_bits == 0) @@ -1006,7 +1031,12 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, div = cprman_read(cprman, data->div_reg); - return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); + rate = bcm2835_clock_rate_from_divisor(clock, parent_rate, div); + + if (data->round_up) + rate = bcm2835_round_rate(rate); + + return rate; } static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock) @@ -2143,7 +2173,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .div_reg = CM_UARTDIV, .int_bits = 10, .frac_bits = 12, - .tcnt_mux = 28), + .tcnt_mux = 28, + .round_up = true), /* TV encoder clock. Only operating frequency is 108Mhz. */ [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( -- 2.35.3