Patch "clk: bcm2835: Round UART input clock up" has been added to the 5.19-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    clk: bcm2835: Round UART input clock up

to the 5.19-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     clk-bcm2835-round-uart-input-clock-up.patch
and it can be found in the queue-5.19 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 23e9ed21ce2d11171b0832117e56a58eda11a034
Author: Ivan T. Ivanov <iivanov@xxxxxxx>
Date:   Mon Sep 12 11:13:04 2022 +0300

    clk: bcm2835: Round UART input clock up
    
    [ Upstream commit f690a4d7a8f66430662975511c86819dc9965bcc ]
    
    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 <phil@xxxxxxxxxxxxxxx>
    Signed-off-by: Ivan T. Ivanov <iivanov@xxxxxxx>
    Reviewed-by: Stefan Wahren <stefan.wahren@xxxxxxxx>
    Link: https://lore.kernel.org/r/20220912081306.24662-1-iivanov@xxxxxxx
    Signed-off-by: Stephen Boyd <sboyd@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index f1102b4c7e88..e74fe6219d14 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -30,6 +30,7 @@
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/math.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -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 unsigned 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(



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux