Fix variable CPU clock for MPC859/866 systems for low CPU clocks
diff --git a/CHANGELOG b/CHANGELOG
index 316e47f..6a14d02 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@
Changes since U-Boot 1.0.1:
======================================================================
+* Fix variable CPU clock for MPC859/866 systems for low CPU clocks
+
* Implement adaptive SDRAM timing configuration based on actual CPU
clock frequency for INCA-IP; fix problem with board hanging when
switching from 150MHz to 100MHz
diff --git a/README b/README
index 58267f1..61d55d4 100644
--- a/README
+++ b/README
@@ -415,12 +415,28 @@
Define exactly one of
CONFIG_MPC8240, CONFIG_MPC8245
-- 8xx CPU Options: (if using an 8xx cpu)
+- 8xx CPU Options: (if using an MPC8xx cpu)
Define one or more of
CONFIG_8xx_GCLK_FREQ - if get_gclk_freq() cannot work
e.g. if there is no 32KHz
reference PIT/RTC clock
+- 859/866 CPU options: (if using a MPC859 or MPC866 CPU):
+ CFG_866_OSCCLK
+ CFG_866_CPUCLK_MIN
+ CFG_866_CPUCLK_MAX
+ CFG_866_CPUCLK_DEFAULT
+ See doc/README.MPC866
+
+ CFG_MEASURE_CPUCLK
+
+ Define this to measure the actual CPU clock instead
+ of relying on the correctness of the configured
+ values. Mostly useful for board bringup to make sure
+ the PLL is locked at the intended frequency. Note
+ that this requires a (stable) reference clock (32 kHz
+ RTC clock),
+
- Linux Kernel Interface:
CONFIG_CLOCKS_IN_MHZ
diff --git a/board/tqm8xx/tqm8xx.c b/board/tqm8xx/tqm8xx.c
index 8cc86fc..9e9cbd3 100644
--- a/board/tqm8xx/tqm8xx.c
+++ b/board/tqm8xx/tqm8xx.c
@@ -128,14 +128,6 @@
break;
putc (*s);
}
-#if defined(CFG_866_CPUCLK_MIN) && defined(CFG_866_CPUCLK_MAX)
- printf (" [%d.%d...%d.%d MHz]",
- CFG_866_CPUCLK_MIN / 1000000,
- ((CFG_866_CPUCLK_MIN % 1000000) + 50000) / 100000,
- CFG_866_CPUCLK_MAX / 1000000,
- ((CFG_866_CPUCLK_MAX % 1000000) + 50000) / 100000
- );
-#endif
putc ('\n');
return (0);
diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c
index 3fb97b0..81d2047 100644
--- a/cpu/mpc8xx/cpu.c
+++ b/cpu/mpc8xx/cpu.c
@@ -123,10 +123,22 @@
else
printf ("unknown M%s (0x%08x)", id_str, k);
- printf (" at %s MHz:", strmhz (buf, clock));
- printf (" %u kB I-Cache", checkicache () >> 10);
- printf (" %u kB D-Cache", checkdcache () >> 10);
+#if defined(CFG_866_CPUCLK_MIN) && defined(CFG_866_CPUCLK_MAX)
+ printf (" at %s MHz [%d.%d...%d.%d MHz]\n ",
+ strmhz (buf, clock),
+ CFG_866_CPUCLK_MIN / 1000000,
+ ((CFG_866_CPUCLK_MIN % 1000000) + 50000) / 100000,
+ CFG_866_CPUCLK_MAX / 1000000,
+ ((CFG_866_CPUCLK_MAX % 1000000) + 50000) / 100000
+ );
+#else
+ printf (" at %s MHz: ", strmhz (buf, clock));
+#endif
+ printf ("%u kB I-Cache %u kB D-Cache",
+ checkicache () >> 10,
+ checkdcache () >> 10
+ );
/* do we have a FEC (860T/P or 852/859/866)? */
diff --git a/cpu/mpc8xx/serial.c b/cpu/mpc8xx/serial.c
index a875963..71f3ae1 100644
--- a/cpu/mpc8xx/serial.c
+++ b/cpu/mpc8xx/serial.c
@@ -71,11 +71,11 @@
static void serial_setdivisor(volatile cpm8xx_t *cp)
{
DECLARE_GLOBAL_DATA_PTR;
- int divisor=gd->cpu_clk/16/gd->baudrate;
+ int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
if(divisor/16>0x1000) {
/* bad divisor, assume 50Mhz clock and 9600 baud */
- divisor=(50*1000*1000)/16/9600;
+ divisor=(50*1000*1000 + 8*9600)/16/9600;
}
#ifdef CFG_BRGCLK_PRESCALE
diff --git a/cpu/mpc8xx/speed.c b/cpu/mpc8xx/speed.c
index 8583eef..8f8efce 100644
--- a/cpu/mpc8xx/speed.c
+++ b/cpu/mpc8xx/speed.c
@@ -25,7 +25,7 @@
#include <mpc8xx.h>
#include <asm/processor.h>
-#ifndef CONFIG_TQM866M
+#if !defined(CONFIG_TQM866M) || defined(CFG_MEASURE_CPUCLK)
#define PITC_SHIFT 16
#define PITR_SHIFT 16
@@ -170,6 +170,10 @@
#endif
}
+#endif
+
+#if !defined(CONFIG_TQM866M)
+
/*
* get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
* or (if it is not defined) measure_gclk() (which uses the ref clock)
@@ -230,6 +234,9 @@
cpuclk = CFG_866_CPUCLK_DEFAULT;
gd->cpu_clk = init_pll_866 (cpuclk);
+#if defined(CFG_MEASURE_CPUCLK)
+ gd->cpu_clk = measure_gclk ();
+#endif
if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0)
gd->bus_clk = gd->cpu_clk;
@@ -269,8 +276,19 @@
char mfi, mfn, mfd, s, pdf;
long step_mfi, step_mfn;
- pdf = 0;
- if (clk < 80000000) {
+ if (clk < 20000000) {
+ clk *= 2;
+ pdf = 1;
+ } else {
+ pdf = 0;
+ }
+
+ if (clk < 40000000) {
+ s = 2;
+ step_mfi = CFG_866_OSCCLK / 4;
+ mfd = 7;
+ step_mfn = CFG_866_OSCCLK / 30;
+ } else if (clk < 80000000) {
s = 1;
step_mfi = CFG_866_OSCCLK / 2;
mfd = 14;
@@ -294,13 +312,14 @@
/* Calculate effective clk
*/
- n = (mfi * step_mfi) + (mfn * step_mfn);
+ n = ((mfi * step_mfi) + (mfn * step_mfn)) / (pdf + 1);
immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
| PLPRCR_MFD_MSK | PLPRCR_S_MSK
- | PLPRCR_MFI_MSK | PLPRCR_DBRMO))
+ | PLPRCR_MFI_MSK | PLPRCR_DBRMO
+ | PLPRCR_PDF_MSK))
| (mfn << PLPRCR_MFN_SHIFT)
| (mfd << PLPRCR_MFD_SHIFT)
| (s << PLPRCR_S_SHIFT)
diff --git a/doc/README.MPC866 b/doc/README.MPC866
index 1464a40..42abac8 100644
--- a/doc/README.MPC866
+++ b/doc/README.MPC866
@@ -12,6 +12,10 @@
CPUCLK_MAX limits, the specified value is used. Otherwise, the
default CPU clock value is set.
+Please make sure you understand what you are doing, and understand
+the restrictions of your hardware (board, processor). For example,
+ethernet will stop working for CPU clock frequencies below 25 MHz.
+
Please note that for now the new clock-handling code has been enabled
for the TQM866M board only, even though it should be pretty much
common for other MPC859 / MPC866 based boards also. Our intention
diff --git a/include/configs/TQM866M.h b/include/configs/TQM866M.h
index a5a759f..3aabfe6 100644
--- a/include/configs/TQM866M.h
+++ b/include/configs/TQM866M.h
@@ -37,12 +37,19 @@
#define CONFIG_TQM866M 1 /* ...on a TQM8xxM module */
#define CFG_866_OSCCLK 10000000 /* 10 MHz - PLL input clock */
-#define CFG_866_CPUCLK_MIN 10000000 /* 10 MHz - CPU minimum clock */
+#define CFG_866_CPUCLK_MIN 15000000 /* 15 MHz - CPU minimum clock */
#define CFG_866_CPUCLK_MAX 133000000 /* 133 MHz - CPU maximum clock */
#define CFG_866_CPUCLK_DEFAULT 50000000 /* 50 MHz - CPU default clock */
/* (it will be used if there is no */
/* 'cpuclk' variable with valid value) */
+#undef CFG_MEASURE_CPUCLK /* Measure real cpu clock */
+ /* (function measure_gclk() */
+ /* will be called) */
+#ifdef CFG_MEASURE_CPUCLK
+#define CFG_8XX_XIN 10000000 /* measure_gclk() needs this */
+#endif
+
#define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */
#define CONFIG_BAUDRATE 115200 /* console baudrate = 115kbps */