Download raw body.
riscv: implement clock for Allwinner D1
Hola! tech@.
I messed up the formatting a few times in the previous thread because of
my email client, and I also seem to have confused everyone with inline text
and attachments, so I apologize for the noise again...
I tried to implement a clock for the D1 cpu, and it seems
like I succeeded because it seems to be works.
Tested on MangoPI MQ Pro ( rev 1.4 )
Index: sxiccmu.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/sxiccmu.c,v
diff -u -p -u -r1.38 sxiccmu.c
--- sxiccmu.c 7 Mar 2024 01:04:16 -0000 1.38
+++ sxiccmu.c 18 Jul 2026 10:14:51 -0000
@@ -1260,11 +1260,19 @@ sxiccmu_a80_get_frequency(struct sxiccmu
#define D1_PLL_CPU_CTRL_REG 0x0000
#define D1_PLL_CPU_FACTOR_M(x) (((x) >> 0) & 0x3)
#define D1_PLL_CPU_FACTOR_N(x) (((x) >> 8) & 0xff)
+#define D1_PLL_CPU_ENABLE (1U << 31)
+#define D1_PLL_CPU_LDO_EN (1U << 30)
+#define D1_PLL_CPU_LOCK_EN (1U << 29)
+#define D1_PLL_CPU_LOCK (1U << 28)
+#define D1_PLL_CPU_OUT_EN (1U << 27)
+#define D1_PLL_CPU_FACTOR_M_MASK (0x3 << 0)
+#define D1_PLL_CPU_FACTOR_N_MASK (0xff << 8)
#define D1_RISCV_CLK_REG 0x0d00
#define D1_RISCV_CLK_SEL (7 << 24)
#define D1_RISCV_CLK_SEL_HOSC (0 << 24)
#define D1_RISCV_CLK_SEL_PLL_CPU (5 << 24)
#define D1_RISCV_DIV_CFG_FACTOR_M(x) (((x) >> 0) & 0x1f)
+#define D1_RISCV_DIV_CFG_FACTOR_M_MASK (0x1f << 0)
#define D1_PSI_CLK_REG 0x0510
#define D1_PSI_CLK_FACTOR_N(x) (((x) >> 8) & 0x3)
#define D1_PSI_CLK_FACTOR_M(x) (((x) >> 0) & 0x3)
@@ -1965,6 +1973,48 @@ sxiccmu_d1_mmc_set_frequency(struct sxic
}
int
+sxiccmu_d1_riscv_set_frequency(struct sxiccmu_softc *sc, uint32_t freq)
+{
+ uint32_t reg, m, n;
+ int lock_timeout = 1000;
+
+ if (freq < 24000000)
+ return -1;
+ n = freq / 24000000;
+ if (n > 256)
+ n = 256;
+ m = 1;
+
+ SXICMS4(sc, D1_RISCV_CLK_REG, D1_RISCV_CLK_SEL, D1_RISCV_CLK_SEL_HOSC);
+ delay(10);
+
+ SXICLR4(sc, D1_PLL_CPU_CTRL_REG, D1_PLL_CPU_OUT_EN);
+ reg = SXIREAD4(sc, D1_PLL_CPU_CTRL_REG);
+ reg &= ~(D1_PLL_CPU_FACTOR_N_MASK | D1_PLL_CPU_FACTOR_M_MASK);
+ reg |= ((n - 1) << 8) | ((m - 1) << 0);
+ reg |= D1_PLL_CPU_ENABLE | D1_PLL_CPU_LDO_EN;
+ SXIWRITE4(sc, D1_PLL_CPU_CTRL_REG, reg);
+ SXICLR4(sc, D1_PLL_CPU_CTRL_REG, D1_PLL_CPU_LOCK_EN);
+ SXISET4(sc, D1_PLL_CPU_CTRL_REG, D1_PLL_CPU_LOCK_EN);
+
+ while ((SXIREAD4(sc, D1_PLL_CPU_CTRL_REG) & D1_PLL_CPU_LOCK) == 0) {
+ if (--lock_timeout == 0)
+ return -1;
+ delay(10);
+ }
+
+ delay(20);
+
+ SXISET4(sc, D1_PLL_CPU_CTRL_REG, D1_PLL_CPU_OUT_EN);
+ reg = SXIREAD4(sc, D1_RISCV_CLK_REG);
+ reg &= ~(D1_RISCV_CLK_SEL | D1_RISCV_DIV_CFG_FACTOR_M_MASK);
+ reg |= D1_RISCV_CLK_SEL_PLL_CPU;
+ SXIWRITE4(sc, D1_RISCV_CLK_REG, reg);
+
+ return 0;
+}
+
+int
sxiccmu_d1_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
{
switch (idx) {
@@ -1974,6 +2024,8 @@ sxiccmu_d1_set_frequency(struct sxiccmu_
return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC1_CLK_REG, freq);
case D1_CLK_MMC2:
return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC2_CLK_REG, freq);
+ case D1_CLK_RISCV:
+ return sxiccmu_d1_riscv_set_frequency(sc, freq);
}
printf("%s: 0x%08x\n", __func__, idx);
riscv: implement clock for Allwinner D1