|
|
@@ -21,19 +21,19 @@
|
|
|
#define AHBPLL_FREQ 240000000 //240M
|
|
|
#define GPUPLL_FREQ 500000000 //500M
|
|
|
|
|
|
-#define SYSPLL_SPRD_EN 0//1
|
|
|
-#define AHBPLL_SPRD_EN 0//1
|
|
|
-#define VPUPLL_SPRD_EN 0//1
|
|
|
-//spread spectrum permillage, for example: 5~50,范围越大,效果越好
|
|
|
+#define SYSPLL_SPRD_EN 0
|
|
|
+#define AHBPLL_SPRD_EN 0
|
|
|
+#define VPUPLL_SPRD_EN 0
|
|
|
+//spread spectrum permillage, for example: x~50,范围越大,效果越好
|
|
|
//单次幅度为24M/P1/P2/REF
|
|
|
-//展频测试:固定P1=2 P2=1, REF=12
|
|
|
+//展频测试:固定P1=4, P2=1, REF=4
|
|
|
#define SYSPLL_SPRD_PERM 5 //5~50
|
|
|
-#define AHBPLL_SPRD_PERM 5 //5~50
|
|
|
-#define VPUPLL_SPRD_PERM 3 //3~41
|
|
|
-//spread spectrum clock frequency,for example:20k~100k,越小越稳定(锁定),越大波形越倾斜
|
|
|
-#define SYSPLL_SPRD_FREQ 30000 //30k~100k
|
|
|
-#define AHBPLL_SPRD_FREQ 20000 //20k~100k
|
|
|
-#define VPUPLL_SPRD_FREQ 20000 //20k~100k
|
|
|
+#define AHBPLL_SPRD_PERM 7 //7~50
|
|
|
+#define VPUPLL_SPRD_PERM 4 //4~50
|
|
|
+//spread spectrum clock frequency,for example:1k~100k,越小越稳定(锁定),越大波形越倾斜
|
|
|
+#define SYSPLL_SPRD_FREQ 10000 //perm为5时, 1K <= fre <= 2M, perm为50时, 1K <= fre <= 352K
|
|
|
+#define AHBPLL_SPRD_FREQ 10000 //perm为7时, 1K <= fre <= 2M, perm为50时, 1K <= fre <= 240K
|
|
|
+#define VPUPLL_SPRD_FREQ 10000 //perm为4时, 1K <= fre <= 2M, perm为50时, 1K <= fre <= 181K
|
|
|
|
|
|
static u32 ahb_clk_freq;
|
|
|
static u32 apb_clk_freq;
|
|
|
@@ -122,16 +122,15 @@ static int CLK_SetSprd(u32 pllcfgreg, u32 sprd_permil, u32 sprd_freq)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (sprd_freq < 10000 || sprd_freq > 100000) {
|
|
|
- printf("[%s], invalid freq config.\n", __func__);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
REFDIV = *(u32 *)pllcfgreg & 0x1f;
|
|
|
FBDIV = (*(u32 *)pllcfgreg >> 8) & 0xfff;
|
|
|
FBDIV1 = FBDIV * (1000 + sprd_permil) / 1000;
|
|
|
+/*
|
|
|
+* FBDIV1 >= FBDIV + 1, FBDIV1 <= 500
|
|
|
+* so, sprd_permil >= 1000 / FBDIV + 1, sprd_permil <= (500 - FBDIV) * 1000 / FBDIV
|
|
|
+*/
|
|
|
if (FBDIV1 < 16 || FBDIV1 > 500 || FBDIV1 == FBDIV) {
|
|
|
- printf("FBDIV1 MIN: %d, MAX: %d.\n", (FBDIV + 1) * 1000 / (CLK_GetPLLFreq(SYSCTRL->VPUPLL_CFG) / 1000000), (500 - FBDIV) * 1000 / (CLK_GetPLLFreq(SYSCTRL->VPUPLL_CFG) / 1000000));
|
|
|
+ printf("sprd_permil MIN: %d, MAX: %d.\n", 1000 / FBDIV + 1, MIN((500 - FBDIV) * 1000 / FBDIV, 1000));
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
@@ -142,18 +141,28 @@ static int CLK_SetSprd(u32 pllcfgreg, u32 sprd_permil, u32 sprd_freq)
|
|
|
}
|
|
|
|
|
|
max_offset = FBDIV1 - FBDIV;
|
|
|
- unit_freq = HSE_Value / 4 / REFDIV * FBDIV; //default 4
|
|
|
- sprd_val = unit_freq / max_offset / 2 / sprd_freq;
|
|
|
- if (sprd_val & ~(0xfff)) {
|
|
|
- printf("[%s], sprd_val para except.\n", __func__);
|
|
|
+ unit_freq = HSE_Value / REFDIV;
|
|
|
+ sprd_val = unit_freq / (max_offset * 2 + 1) / sprd_freq;
|
|
|
+/*
|
|
|
+ * sprd_permil fixed, so the coeff(unit_freq / (max_offset * 2 + 1)) is also fixed.
|
|
|
+ * 1 <= sprd_val <= 4096
|
|
|
+ * coeff / 4096 <= sprd_freq <= coeff
|
|
|
+*/
|
|
|
+ if ((sprd_val - 1) & (~(0xfff))) {
|
|
|
+ printf("sprd_val overrun.\n");
|
|
|
+ u32 coeff = unit_freq / (max_offset * 2 + 1);
|
|
|
+ printf("sprd_freq min:%d, max:%d.\n", coeff / 4096, coeff);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ //test
|
|
|
+ //printf("sprd_permil MIN: %d, MAX: %d.\n", MAX(1, 1000 / FBDIV + 1), MIN((500 - FBDIV) * 1000 / FBDIV, 1000));
|
|
|
+ //u32 coeff = unit_freq / (max_offset * 2 + 1);
|
|
|
+ //printf("sprd_freq min:%d, max:%d.\n", coeff / 4096, coeff);
|
|
|
+
|
|
|
val = *(u32 *)pllsprdcfgreg;
|
|
|
- val &= ~(0x1 << 30);
|
|
|
- val &= ~(0xfff << 16);
|
|
|
- val |= (max_offset & 0xfff) << 16;
|
|
|
- val |= sprd_val & 0xfff;
|
|
|
+ val &= ~((0x1 << 30) | (0xfff << 16) | (0xfff << 0));
|
|
|
+ val |= (((max_offset & 0xfff) << 16) | ((sprd_val - 1) & 0xfff));
|
|
|
*(u32 *)pllsprdcfgreg = val;
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -170,16 +179,16 @@ void CLK_SetFreq(u32 pllcfgreg, u64 freq, u8 ensprd)
|
|
|
if (ensprd) {
|
|
|
sprd_permil = SYSPLL_SPRD_PERM;
|
|
|
sprd_freq = SYSPLL_SPRD_FREQ;
|
|
|
- refdiv = 12;
|
|
|
- } else {
|
|
|
- postdiv1 = 4;
|
|
|
+ refdiv = 4;
|
|
|
}
|
|
|
+ postdiv1 = 4;
|
|
|
} else if (pllcfgreg == (u32)&SYSCTRL->AHBPLL_CFG) {
|
|
|
SYSCTRL->AHBPLL_SPRD_CTL |= (1 << 30);
|
|
|
if (ensprd) {
|
|
|
sprd_permil = AHBPLL_SPRD_PERM;
|
|
|
sprd_freq = AHBPLL_SPRD_FREQ;
|
|
|
- refdiv = 12;
|
|
|
+ refdiv = 4;
|
|
|
+ postdiv1 = 4;
|
|
|
} else {
|
|
|
postdiv1 = 3;
|
|
|
}
|
|
|
@@ -188,7 +197,8 @@ void CLK_SetFreq(u32 pllcfgreg, u64 freq, u8 ensprd)
|
|
|
if (ensprd) {
|
|
|
sprd_permil = VPUPLL_SPRD_PERM;
|
|
|
sprd_freq = VPUPLL_SPRD_FREQ;
|
|
|
- refdiv = 12;
|
|
|
+ refdiv = 4;
|
|
|
+ postdiv1 = 4;
|
|
|
}
|
|
|
} else {
|
|
|
if (ensprd) {
|
|
|
@@ -197,6 +207,11 @@ void CLK_SetFreq(u32 pllcfgreg, u64 freq, u8 ensprd)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (refdiv < 1 || refdiv> 4) {
|
|
|
+ printf("pll refdiv illegal, please reconfigure refdiv.\n");
|
|
|
+ while(1);
|
|
|
+ }
|
|
|
+
|
|
|
/* POSTDIV1 should >= POSTDIV2 */
|
|
|
fbdiv = (freq * postdiv1 * postdiv2 * refdiv / HSE_Value) & 0xfff; //freq / 2
|
|
|
if (fbdiv < 16 || fbdiv > 500) {
|