Re: Allwinner H3/H5: PLL1 (CPU_PLL) setting

classic Classic list List threaded Threaded
1 message Options
adr
Reply | Threaded
Open this post in threaded view
|

Re: Allwinner H3/H5: PLL1 (CPU_PLL) setting

adr
> Hi,
>
> Previously I found OpenBSD-6.6, 6.7 and -current did not work on
> my Orange Pi PC (Allwinner H3).
>
> For these days I was looking for what caused this problem, and
> finally I found the M field of H3_PLL_CPUX_CTRL_REG (@0x01c20000)
> made thing worse.
>
> This, M value should be 2. If this is 1, system will be hang.
> Here is easy test method that writing value 0x90001431 (default)
> and 0x90001410, they produce same clock frequency 1008MHz.

Hello Takayoshi,

I've being testing an h3 machine (orangepi-one) that was unusable,
with hangs and random vm faults mostly at boot time.

Thanks for pointing to the problem!

It seems that the PLL is not been stabilized although LOCK is read as
set. You can check it by putting a delay in sxiccmu_h3_set_frequency
after H3_PLL_CPUX_LOCK is tested, delay(200) is sufficient, the machine
will boot ok.

Using a divider seams to make the stabilizing faster, but this
random behavior is a little tricky to make a solution of it, and
in the future other problems could arise.

What about gating the PLL before applying the multipliers and ungating
it afterwards?

Note that the datasheet warns about the need of waiting 8 cycles of the
current clock after changing CPUX_CLK_SRC_SEL, So it may be helpful to
add a small delay after setting CPUX_CLK_SRC_SEL. I put delay(1) as a
reference, I'm starting to look under the hood of OpenBSD, I don't know
what is the preffered way to deal with such a small delay in cycles in
this place.
---------------------------------------------------------------
--- /usr/src/sys/dev/fdt/sxiccmu.c.orig Wed Jul  8 21:23:35 2020
+++ /usr/src/sys/dev/fdt/sxiccmu.c Fri Jul 10 21:35:49 2020
@@ -1158,6 +1158,7 @@
 
 /* Allwinner H3/H5 */
 #define H3_PLL_CPUX_CTRL_REG 0x0000
+#define H3_PLL_CPUX_ENABLE (1 << 31)
 #define H3_PLL_CPUX_LOCK (1 << 28)
 #define H3_PLL_CPUX_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3)
 #define H3_PLL_CPUX_OUT_EXT_DIVP_MASK (0x3 << 16)
@@ -1644,7 +1645,12 @@
  while (n >= 1 && (24000000 * n * k) > freq)
  n--;
 
+ /* Gate the PLL first */
  reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG);
+ reg &= ~H3_PLL_CPUX_ENABLE;
+ SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
+
+ /* Set factors and external divider. */
  reg &= ~H3_PLL_CPUX_OUT_EXT_DIVP_MASK;
  reg &= ~H3_PLL_CPUX_FACTOR_N_MASK;
  reg &= ~H3_PLL_CPUX_FACTOR_K_MASK;
@@ -1653,6 +1659,10 @@
  reg |= ((k - 1) << H3_PLL_CPUX_FACTOR_K_SHIFT);
  SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
 
+ /* Ungate the PLL */
+ reg |= H3_PLL_CPUX_ENABLE;
+ SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
+
  /* Wait for PLL to lock. */
  while ((SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG) &
     H3_PLL_CPUX_LOCK) == 0)
@@ -1665,6 +1675,8 @@
  reg &= ~H3_CPUX_CLK_SRC_SEL;
  reg |= H3_CPUX_CLK_SRC_SEL_OSC24M;
  SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg);
+ /* Must wait at least 8 cycles of the current clock. */
+ delay(1);
 
  error = sxiccmu_h3_set_frequency(sc, H3_CLK_PLL_CPUX, freq);
 
@@ -1673,6 +1685,7 @@
  reg &= ~H3_CPUX_CLK_SRC_SEL;
  reg |= H3_CPUX_CLK_SRC_SEL_PLL_CPUX;
  SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg);
+ delay(1);
  return error;
  case H3_CLK_MMC0:
  case H3_CLK_MMC1:
---------------------------------------------------------------

At least the problems at boot are gone, but there is still some
instability with this soc. These socs are very sensitive to high
frequencies and the heat they produce. I think DVFS is a must here,
I will try setting hw.setperf=90 for a while.

Regards,
adr.