Thread (15 messages) 15 messages, 2 authors, 2016-01-26

Re: [PATCH v6 2/3] spi: sun4i: Fix clock calculations to be predictable and never exceed the requested rate

From: Maxime Ripard <hidden>
Date: 2016-01-10 19:44:56
Also in: linux-arm-kernel, linux-spi, lkml

On Mon, Dec 28, 2015 at 05:22:35PM +0100, Marcus Weseloh wrote:
Hi again,

2015-12-28 0:29 GMT+01:00 Marcus Weseloh [off-list ref]:
quoted
2015-12-27 22:09 GMT+01:00 Maxime Ripard [off-list ref]:
[...]
quoted
[...]
quoted
quoted
-     /* Ensure that we have a parent clock fast enough */
+     /*
+      * Ensure that the parent clock is set to twice the max speed
+      * of the spi device (possibly rounded up by the clk driver)
+      */
      mclk_rate = clk_get_rate(sspi->mclk);
-     if (mclk_rate < (2 * tfr->speed_hz)) {
-             clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
+     if (spi->max_speed_hz != sspi->cur_max_speed ||
+         mclk_rate != sspi->cur_mclk) {
Do you need to cache the values? As far as I'm aware, you end up doing
the computation all the time anyway.
By caching the values we optimize the case when a single SPI slave
device (or even multiple slave devices with the same max_speed) are
used multiple times in a row. In that case, we're saving two calls:
clk_set_rate and clk_get_rate. I was unsure about how expensive the
clk_* calls were, so I thought it would be safer use caching. But
maybe it's not worth the extra code?

Oh, and I just noticed a mistake in the comment: the clock driver
rounds up _or_ down, so I should drop the "up".
As I'm looking further into this, I think the comment should read
"possibly rounded down", as the clk framework is expected to set a
frequency that is less or equal to the requested frequency.
AFAIK, there's no such expectation in the clock framework. You
treating this from a maximum frequency perspective, but it would be
the exact opposite if you were talking about a minimum frequency, as
might be the case for other consumers.
So the effect I was seeing (that I got a frequency higher than the
requested one) is actually a bug!? Further details below.
quoted
[...]
quoted
quoted
-     div = mclk_rate / (2 * tfr->speed_hz);
-     if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
-             if (div > 0)
-                     div--;
-
+     div = DIV_ROUND_UP(mclk_rate, 2 * tfr->speed_hz) - 1;
Isn't it exactly the same thing as mclk_rate / (2 * tfr->speed_hz) ?
It is quite often, but not in all cases. The plain division rounds to
the nearest integer, so it rounds down sometimes. Consider the
following case: we have a slow SPI device with a spi-max-frequency of
50kHz. Our clock driver can't find a clock as slow as 100kHz, so it
sets mclk to 214,285Hz.
That clk_set_rate sets a higher frequency than requested seems to be a
problem in itself. I had a look at clk/sunxi/clk-mod0.c and noticed a
few small problems there. Will post an RFC patch in a couple of
minutes.
Did you post these patches already? I think I missed them if that's
the case.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help