diff mbox series

clk: bcm2835: Round UART input clock up

Message ID 20220404085822.84135-1-iivanov@suse.de (mailing list archive)
State New, archived
Headers show
Series clk: bcm2835: Round UART input clock up | expand

Commit Message

Ivan T . Ivanov April 4, 2022, 8:58 a.m. UTC
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 baudrate
== 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.

This is reworked version of a downstream fix:
https://github.com/raspberrypi/linux/commit/ab3f1b39537f6d3825b8873006fbe2fc5ff057b7

Cc: Phil Elwell <phil@raspberrypi.org>
Signed-off-by: Ivan T. Ivanov <iivanov@suse.de>
---
 drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

Comments

kernel test robot April 4, 2022, 10:59 a.m. UTC | #1
Hi "Ivan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on v5.18-rc1 next-20220404]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Ivan-T-Ivanov/clk-bcm2835-Round-UART-input-clock-up/20220404-170105
base:   https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
config: riscv-randconfig-r042-20220404 (https://download.01.org/0day-ci/archive/20220404/202204041850.zEjvoN6Y-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/79c34b5361c9ab155da3175cfc964b67b9a06eab
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Ivan-T-Ivanov/clk-bcm2835-Round-UART-input-clock-up/20220404-170105
        git checkout 79c34b5361c9ab155da3175cfc964b67b9a06eab
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash drivers/clk/bcm/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/clk/bcm/clk-bcm2835.c:997:15: warning: no previous prototype for 'bcm2835_clock_round' [-Wmissing-prototypes]
     997 | unsigned long bcm2835_clock_round(unsigned long clk)
         |               ^~~~~~~~~~~~~~~~~~~


vim +/bcm2835_clock_round +997 drivers/clk/bcm/clk-bcm2835.c

   996	
 > 997	unsigned long bcm2835_clock_round(unsigned long clk)
   998	{
   999		unsigned long scaler;
  1000	
  1001		/*
  1002		 * If increasing a clock by less than 0.1% changes it
  1003		 * from ..999.. to ..000.., round up.
  1004		 */
  1005		scaler = 1;
  1006		while (scaler * 100000 < clk)
  1007			scaler *= 10;
  1008		if ((clk + scaler - 1) / scaler % 1000 == 0)
  1009			clk = (clk / scaler + 1) * scaler;
  1010	
  1011		return clk;
  1012	}
  1013
diff mbox series

Patch

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 3ad20e75fd23..f293cde427b7 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -502,6 +502,8 @@  struct bcm2835_clock_data {
 	bool low_jitter;
 
 	u32 tcnt_mux;
+
+	bool round_up;
 };
 
 struct bcm2835_gate_data {
@@ -992,12 +994,30 @@  static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
 	return temp;
 }
 
+unsigned long bcm2835_clock_round(unsigned long clk)
+{
+	unsigned long scaler;
+
+	/*
+	 * If increasing a clock by less than 0.1% changes it
+	 * from ..999.. to ..000.., round up.
+	 */
+	scaler = 1;
+	while (scaler * 100000 < clk)
+		scaler *= 10;
+	if ((clk + scaler - 1) / scaler % 1000 == 0)
+		clk = (clk / scaler + 1) * scaler;
+
+	return clk;
+}
+
 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)
@@ -1005,7 +1025,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_clock_round(rate);
+
+	return rate;
 }
 
 static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
@@ -2142,7 +2167,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(