[U-Boot] PATCH: mpc8xx PLPRCR (init_pll_866)

Spencer Putt Spencer_Putt at raytheon.com
Wed Nov 19 19:14:19 CET 2008


Signed-off-by:
Spencer Putt
Raytheon Company

The current init_pll_866 makes a bad assumption for the oscillator.  A
board with a slower oscillator may lead to PLPRCR fields overflowing their
bounds and making the board not boot.  This patch should more accurately
set the PLPRCR regardless of the oscillator, and will increase the
probability a board will boot by doing some bounds checking.

--- cpu_mpc8xx_speed.c 2008-10-16 15:37:10.000000000 -0400
+++ speed.c 2008-10-16 15:35:44.000000000 -0400
@@ -313,56 +313,60 @@
}
/* Configure PLL for MPC866/859/885 CPU series
- * PLL multiplication factor is set to the value nearest to the desired
clk,
- * assuming a oscclk of 10 MHz.
+ * PLL multiplication factor is set to the value nearest to the desired
clk
+ * If the clk is unattainable, it is set to the highest possible, OSCLK*16
*/
static long init_pll_866 (long clk)
{
extern void plprcr_write_866 (long);
volatile immap_t *immr = (immap_t *) CFG_IMMR;
- long n, plprcr;
- char mfi, mfn, mfd, s, pdf;
- long step_mfi, step_mfn;
-
- if (clk < 20000000) {
- clk *= 2;
- pdf = 1;
- } else {
- pdf = 0;
- }
+ long n, plprcr, mfi;
+ char mfn, mfd, s;
+ long pdf = -1;
+ long step_mfi, step_mfn;
+
+/* The goal is to make (mfi / pdf) * (OSCLK >> s) = clk
+ *
+ * Generally having s as high as possible is desired.
+ * This is because the final resolution depends on the
+ * the OSCLK freq >> s. So let's see how we can manipulate
+ * the predivision factor (pdf) to allow s to be as large
+ * as possible.
+ */
+ s = 2;
+ mfi = clk / (CONFIG_8xx_OSCLK / 4);
- if (clk < 40000000) {
- s = 2;
- step_mfi = CONFIG_8xx_OSCLK / 4;
- mfd = 7;
- step_mfn = CONFIG_8xx_OSCLK / 30;
- } else if (clk < 80000000) {
+ if (mfi > 16 * 2) {
+ s = 0;
+ } else if (mfi > 16) {
s = 1;
- step_mfi = CONFIG_8xx_OSCLK / 2;
- mfd = 14;
- step_mfn = CONFIG_8xx_OSCLK / 30;
+ }
+
+ /* Modify pdf until mfi is in range (5 to 15) */
+ do {
+ step_mfi = (CONFIG_8xx_OSCLK >> s) / (++pdf + 1);
+ mfi = clk / step_mfi;
+ } while (mfi < 5 && pdf < 16);
+
+ /* Set the denominator to 32 */
+ mfd = 31;
+ step_mfn = step_mfi / (mfd + 1);
+
+ /* Check mfi's range (the frequency may be unattainable) */
+ if (mfi > 15) {
+ /* FIXME: possibly warn the user */
+ mfi = 15;
+ mfn = 31;
} else {
- s = 0;
- step_mfi = CONFIG_8xx_OSCLK;
- mfd = 29;
- step_mfn = CONFIG_8xx_OSCLK / 30;
+ /* Find the numerator (n/32) */
+ mfn = (clk - (mfi * step_mfi)) / step_mfn;
}
- /* Calculate integer part of multiplication factor
- */
- n = clk / step_mfi;
- mfi = (char)n;
-
- /* Calculate numerator of fractional part of multiplication factor
- */
- n = clk - (n * step_mfi);
- mfn = (char)(n / step_mfn);
-
- /* Calculate effective clk
- */
- n = ((mfi * step_mfi) + (mfn * step_mfn)) / (pdf + 1);
+ /* Calculate effective clock */
+ n = (mfi * step_mfi) + (mfn * step_mfn);
+ /* Unlock the PLPRCR */
immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
@@ -379,6 +383,7 @@
plprcr |= PLPRCR_DBRMO;
plprcr_write_866 (plprcr); /* set value using SIU4/9 workaround */
+
immr->im_clkrstk.cark_plprcrk = 0x00000000;
return (n);



More information about the U-Boot mailing list