* [PATCH v2] clk: bcm2835: Round UART input clock up
@ 2022-04-04 12:51 Ivan T. Ivanov
2022-04-14 10:56 ` Ivan T. Ivanov
0 siblings, 1 reply; 2+ messages in thread
From: Ivan T. Ivanov @ 2022-04-04 12:51 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Nicolas Saenz Julienne,
Florian Fainelli, Ray Jui, Scott Branden,
bcm-kernel-feedback-list, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: Ivan T. Ivanov, Phil Elwell, kernel test robot, linux-clk,
linux-rpi-kernel, linux-arm-kernel, linux-kernel, linux-riscv
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>
---
Changes since v1
Make bcm2835_clock_round() static to fix following warning
when compiling for riscv:
drivers/clk/bcm/clk-bcm2835.c:997:15: warning: no previous prototype for 'bcm2835_clock_round' [-Wmissing-prototypes]
Reported-by: kernel test robot <lkp@intel.com>
drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 3ad20e75fd23..c29b643d1bf5 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;
}
+static 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(
--
2.26.2
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] clk: bcm2835: Round UART input clock up
2022-04-04 12:51 [PATCH v2] clk: bcm2835: Round UART input clock up Ivan T. Ivanov
@ 2022-04-14 10:56 ` Ivan T. Ivanov
0 siblings, 0 replies; 2+ messages in thread
From: Ivan T. Ivanov @ 2022-04-14 10:56 UTC (permalink / raw)
To: Stefan Wahren
Cc: Michael Turquette, Stephen Boyd, Nicolas Saenz Julienne,
Florian Fainelli, Ray Jui, Scott Branden, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Phil Elwell, kernel test robot,
bcm-kernel-feedback-list, linux-clk, linux-rpi-kernel,
linux-arm-kernel, linux-kernel, linux-riscv
Hi Stefan,
Please, could you take a look into following patch?
Thanks!
Ivan
On 04-04 15:51, Ivan T. Ivanov wrote:
> Subject: [PATCH v2] clk: bcm2835: Round UART input clock up
> Message-Id: <20220404125113.80239-1-iivanov@suse.de>
>
> 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>
> ---
> Changes since v1
> Make bcm2835_clock_round() static to fix following warning
> when compiling for riscv:
> drivers/clk/bcm/clk-bcm2835.c:997:15: warning: no previous prototype for 'bcm2835_clock_round' [-Wmissing-prototypes]
> Reported-by: kernel test robot <lkp@intel.com>
>
> drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++++++++++++++++++--
> 1 file changed, 28 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
> index 3ad20e75fd23..c29b643d1bf5 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;
> }
>
> +static 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(
> --
> 2.26.2
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-04-14 10:57 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-04-04 12:51 [PATCH v2] clk: bcm2835: Round UART input clock up Ivan T. Ivanov
2022-04-14 10:56 ` Ivan T. Ivanov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox