> 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.