summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2007-08-13 09:05:33 +0200
committerStefan Roese <sr@denx.de>2007-08-13 09:05:33 +0200
commit273db7e1bdd1937e32f1d4507321bb721ebd3118 (patch)
tree71b1c8710bdfd10dbffca0cf3f0aa0255e064c17
parent35d22f957a85a22bb3cd1ad084fa5404620d1c42 (diff)
downloadu-boot-imx-273db7e1bdd1937e32f1d4507321bb721ebd3118.zip
u-boot-imx-273db7e1bdd1937e32f1d4507321bb721ebd3118.tar.gz
u-boot-imx-273db7e1bdd1937e32f1d4507321bb721ebd3118.tar.bz2
ppc4xx: Fix problem in PLL clock calculation
This patch was originall provided by David Mitchell <dmitchell@amcc.com> and fixes a bug in the PLL clock calculation. Signed-off-by: Stefan Roese <sr@denx.de>
-rw-r--r--cpu/ppc4xx/serial.c9
-rw-r--r--cpu/ppc4xx/speed.c33
-rw-r--r--include/ppc405.h2
3 files changed, 26 insertions, 18 deletions
diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c
index e62dd9d..a75e5ee 100644
--- a/cpu/ppc4xx/serial.c
+++ b/cpu/ppc4xx/serial.c
@@ -448,12 +448,17 @@ static void serial_divs (int baudrate, unsigned long *pudiv,
unsigned long i;
unsigned long est; /* current estimate */
unsigned long plloutb;
+ unsigned long cpr_pllc;
u32 reg;
+ /* check the pll feedback source */
+ mfcpr(cprpllc, cpr_pllc);
+
get_sys_info(&sysinfo);
- plloutb = ((CONFIG_SYS_CLK_FREQ * sysinfo.pllFwdDiv * sysinfo.pllFbkDiv)
- / sysinfo.pllFwdDivB);
+ plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+ sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * sysinfo.pllFbkDiv) /
+ sysinfo.pllFwdDivB);
udiv = 256; /* Assume lowest possible serial clk */
div = plloutb / (16 * baudrate); /* total divisor */
umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 028b11a..da5330a 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -771,6 +771,7 @@ ulong get_PCI_freq (void)
void get_sys_info (PPC405_SYS_INFO * sysInfo)
{
unsigned long cpr_plld;
+ unsigned long cpr_pllc;
unsigned long cpr_primad;
unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
unsigned long primad_cpudv;
@@ -780,6 +781,7 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Read PLL Mode registers
*/
mfcpr(cprplld, cpr_plld);
+ mfcpr(cprpllc, cpr_pllc);
/*
* Determine forward divider A
@@ -787,20 +789,18 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
/*
- * Determine forward divider B (should be equal to A)
+ * Determine forward divider B
*/
sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
- if (sysInfo->pllFwdDivB == 0) {
+ if (sysInfo->pllFwdDivB == 0)
sysInfo->pllFwdDivB = 8;
- }
/*
* Determine FBK_DIV.
*/
sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
- if (sysInfo->pllFbkDiv == 0) {
+ if (sysInfo->pllFbkDiv == 0)
sysInfo->pllFbkDiv = 256;
- }
/*
* Read CPR_PRIMAD register
@@ -810,30 +810,30 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Determine PLB_DIV.
*/
sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
- if (sysInfo->pllPlbDiv == 0) {
+ if (sysInfo->pllPlbDiv == 0)
sysInfo->pllPlbDiv = 16;
- }
/*
* Determine EXTBUS_DIV.
*/
sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
- if (sysInfo->pllExtBusDiv == 0) {
+ if (sysInfo->pllExtBusDiv == 0)
sysInfo->pllExtBusDiv = 16;
- }
/*
* Determine OPB_DIV.
*/
sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
- if (sysInfo->pllOpbDiv == 0) {
+ if (sysInfo->pllOpbDiv == 0)
sysInfo->pllOpbDiv = 16;
- }
/*
* Determine the M factor
*/
- m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+ if (cpr_pllc & PLLC_SRC_MASK)
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+ else
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
/*
* Determine VCO clock frequency
@@ -845,16 +845,17 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo)
* Determine CPU clock frequency
*/
primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
- if (primad_cpudv == 0) {
+ if (primad_cpudv == 0)
primad_cpudv = 16;
- }
- sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / primad_cpudv;
+ sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / primad_cpudv;
/*
* Determine PLB clock frequency
*/
- sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / sysInfo->pllPlbDiv;
+ sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
}
/********************************************
diff --git a/include/ppc405.h b/include/ppc405.h
index 8e64731..e4522e7 100644
--- a/include/ppc405.h
+++ b/include/ppc405.h
@@ -617,6 +617,8 @@
#define CPR_CLKUPD_ENDVCH_EN 0x20000000 /* Enable CPR Sys. Div. Changes */
#define CPR_PERD0_SPIDV_MASK 0x000F0000 /* SPI Clock Divider */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+
#define PLLD_FBDV_MASK 0x1F000000 /* PLL feedback divider value */
#define PLLD_FWDVA_MASK 0x000F0000 /* PLL forward divider A value */
#define PLLD_FWDVB_MASK 0x00000700 /* PLL forward divider B value */