linux/drivers/clk/meson
Martin Blumenstingl ad9b2b8e53 clk: meson: meson8b: fix incorrect divider mapping in cpu_scale_table
The public S805 datasheet only mentions that
HHI_SYS_CPU_CLK_CNTL1[20:29] contains a divider called "cpu_scale_div".
Unfortunately it does not mention how to use the register contents.

The Amlogic 3.10 GPL kernel sources are using the following code to
calculate the CPU clock based on that register (taken from
arch/arm/mach-meson8/clock.c in the 3.10 Amlogic kernel, shortened to
make it easier to read):
N = (aml_read_reg32(P_HHI_SYS_CPU_CLK_CNTL1) >> 20) & 0x3FF;
if (sel == 3) /* use cpu_scale_div */
  div = 2 * N;
else
  div = ... /* not relevant for this example */
cpu_clk = parent_clk / div;

This suggests that the formula is: parent_rate / 2 * register_value
However, running perf (which can measure the CPU clock rate thanks to
the ARM PMU) shows that this formula is not correct.
This can be reproduced with the following steps:
1. boot into u-boot
2. let the CPU clock run off the XTAL clock:
   mw.l 0xC110419C 0x30 1
3. set the cpu_scale_div register:
   to value 0x1: mw.l 0xC110415C 0x801016A2 1
   to value 0x2: mw.l 0xC110415C 0x802016A2 1
   to value 0x5: mw.l 0xC110415C 0x805016A2 1
4. let the CPU clock run off cpu_scale_div:
   mw.l 0xC110419C 0xbd 1
5. boot Linux
6. run: perf stat -aB stress --cpu 4 --timeout 10
7. check the "cycles" value

I get the following results depending on the cpu_scale_div value:
- (cpu_in_sel - this is the input clock for cpu_scale_div - runs at
   1.2GHz)
- 0x1 = 300MHz
- 0x2 = 200MHz
- 0x5 = 100MHz

This means that the actual formula to calculate the output of the
cpu_scale_div clock is: parent_rate / 2 * (register value + 1).

The register value 0x0 is reserved. When letting the CPU clock run off
the cpu_scale_div while the value is 0x0 the whole board hangs (even in
u-boot).

I also verified this with the TWD timer: when adding this to the .dts
without specifying it's clock it will auto-detect the PERIPH (which is
the input clock of the TWD) clock rate (and the result is shown in the
kernel log). On Meson8, Meson8b and Meson8m2 the PERIPH clock is CPUCLK
divided by 4. This also matched for all three test-cases from above (in
all cases the TWD timer clock rate was approx. one fourth of the CPU
clock rate).

A small note regarding the "fixes" tag: the original issue seems to
exist virtually since forever. Even commit 28b9fcd016 ("clk:
meson8b: Add support for Meson8b clocks") seems to handle this wrong. I
still decided to use commit 251b6fd38b ("clk: meson: rework meson8b
cpu clock") because this is the first commit which gets the CPU hiearchy
correct and thus it's the first commit where the cpu_scale_div register
is used correctly (apart from the bug in the cpu_scale_table).

Fixes: 251b6fd38b ("clk: meson: rework meson8b cpu clock")
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Link: https://lkml.kernel.org/r/20180927085921.24627-2-martin.blumenstingl@googlemail.com
2018-11-23 15:11:57 +01:00
..
axg-aoclk.c clk: meson-axg: Add AO Clock and Reset controller driver 2018-05-15 14:19:43 +02:00
axg-aoclk.h clk: meson-axg: Add AO Clock and Reset controller driver 2018-05-15 14:19:43 +02:00
axg-audio.c clk: meson: axg: round audio system master clocks down 2018-09-26 12:02:00 +02:00
axg-audio.h clk: meson: axg: add the audio clock controller driver 2018-07-09 13:48:26 +02:00
axg.c clk: meson-axg: pcie: drop the mpll3 clock parent 2018-09-26 12:02:00 +02:00
axg.h clk: meson: clk-pll: remove od parameters 2018-09-26 12:01:57 +02:00
clk-mpll.c clk: meson: mpll: add round closest support 2018-05-21 11:31:29 +02:00
clk-phase.c clk: meson: add clk-phase clock driver 2018-07-09 13:47:22 +02:00
clk-pll.c clk: meson: clk-pll: drop hard-coded rates from pll tables 2018-09-26 12:02:00 +02:00
clk-regmap.c This time we have a good set of changes to the core framework that do some 2018-06-09 12:06:24 -07:00
clk-regmap.h clk: meson: use SPDX license identifiers consistently 2018-05-18 12:08:29 +02:00
clk-triphase.c clk: meson: add triple phase clock driver 2018-07-09 13:47:22 +02:00
clkc-audio.h clk: meson: add axg audio sclk divider driver 2018-07-09 13:48:25 +02:00
clkc.h clk: meson: Add vid_pll divider driver 2018-11-23 15:11:56 +01:00
gxbb-aoclk-32k.c clk: meson: use SPDX license identifiers consistently 2018-05-18 12:08:29 +02:00
gxbb-aoclk.c clk: meson: use SPDX license identifiers consistently 2018-05-18 12:08:29 +02:00
gxbb-aoclk.h This time we have a good set of changes to the core framework that do some 2018-06-09 12:06:24 -07:00
gxbb.c clk: meson-gxbb: Add video clocks 2018-11-23 15:11:56 +01:00
gxbb.h dt-bindings: clk: meson-gxbb: Add Video clock bindings 2018-11-23 15:11:56 +01:00
Kconfig clk: meson: axg: add the audio clock controller driver 2018-07-09 13:48:26 +02:00
Makefile clk: meson: Add vid_pll divider driver 2018-11-23 15:11:56 +01:00
meson8b.c clk: meson: meson8b: fix incorrect divider mapping in cpu_scale_table 2018-11-23 15:11:57 +01:00
meson8b.h clk: meson: clk-pll: remove od parameters 2018-09-26 12:01:57 +02:00
meson-aoclk.c clk: meson: aoclk: refactor common code into dedicated file 2018-05-15 14:19:42 +02:00
meson-aoclk.h clk: meson: aoclk: refactor common code into dedicated file 2018-05-15 14:19:42 +02:00
sclk-div.c clk: meson: add axg audio sclk divider driver 2018-07-09 13:48:25 +02:00
vid-pll-div.c clk: meson: Add vid_pll divider driver 2018-11-23 15:11:56 +01:00