* Patch by Martin Krause, 17 Jul 2003:
add delay to get I2C working with "imm" command and s3c24x0_i2c.c
* Patch by Richard Woodruff, 17 July 03:
- Fixed bug in OMAP1510 baud rate divisor settings.
* Patch by Nye Liu, 16 July 2003:
MPC860FADS fixes:
- add MPC86xADS support (uses MPC86xADS.h)
- add 866P/T core support (also MPC859T/MPC859DSL/MPC852T)
o PLPRCR changes
o BRG changes (EXTAL/XTAL restricted to 10MHz)
o don't trust gclk() software measurement by default, depend on
CONFIG_8xx_GCLK_FREQ
- add DRAM SIMM not installed detection
- use more "correct" SDRAM initialization sequence
- allow different SDRAM sizes (8xxADS has 8M)
- default DER is 0
- remove unused MAMR defines from FADS860T.h (all done in fads.c)
- rename MAMR/MBMR defines to be more consistent. Should eventually
be merged into MxMR to better reflect the PowerQUICC datasheet.
* Patch by Yuli Barcohen, 16 Jul 2003:
support new Motorola PQ2FADS-ZU evaluation board which replaced
MPC8260ADS and MPC8266ADS
diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c
index 4e23228..b95e06f 100644
--- a/cpu/mpc8xx/cpu.c
+++ b/cpu/mpc8xx/cpu.c
@@ -42,12 +42,23 @@
static char *cpu_warning = "\n " \
"*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
-#if ((defined(CONFIG_MPC860) || defined(CONFIG_MPC855)) && \
+#if ((defined(CONFIG_MPC86x) || defined(CONFIG_MPC855)) && \
!defined(CONFIG_MPC862))
-# ifdef CONFIG_MPC855
+
+# if defined(CONFIG_MPC855)
# define ID_STR "PC855"
+# elif defined(CONFIG_MPC852T)
+# define ID_STR "PC852T"
+# elif defined(CONFIG_MPC859T)
+# define ID_STR "PC859T"
+# elif defined(CONFIG_MPC859DSL)
+# define ID_STR "PC859DSL"
+# elif defined(CONFIG_MPC860P)
+# define ID_STR "PC860P"
+# elif defined(CONFIG_MPC866T)
+# define ID_STR "PC866T"
# else
-# define ID_STR "PC860"
+# define ID_STR "PC86x" /* unknown 86x chip */
# endif
static int check_CPU (long clock, uint pvr, uint immr)
@@ -68,6 +79,10 @@
m = 0;
switch (k) {
+#ifdef CONFIG_MPC866_et_al
+ /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
+ case 0x08000003: pre = 'M'; suf = ""; m = 1; break;
+#else
case 0x00020001: pre = 'p'; suf = ""; break;
case 0x00030001: suf = ""; break;
case 0x00120003: suf = "A"; break;
@@ -76,17 +91,16 @@
case 0x00200004: suf = "B"; break;
case 0x00300004: suf = "C"; break;
- case 0x00310004: suf = "C1"; m = 1;
- break;
+ case 0x00310004: suf = "C1"; m = 1; break;
case 0x00200064: mid = "SR"; suf = "B"; break;
case 0x00300065: mid = "SR"; suf = "C"; break;
case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break;
case 0x05010000: suf = "D3"; m = 1; break;
case 0x05020000: suf = "D4"; m = 1; break;
-
/* this value is not documented anywhere */
case 0x40000000: pre = 'P'; suf = "D"; m = 1; break;
+#endif
default: suf = NULL; break;
}
@@ -101,7 +115,7 @@
printf (" %u kB I-Cache", checkicache () >> 10);
printf (" %u kB D-Cache", checkdcache () >> 10);
- /* lets check and see if we're running on a 860T (or P?) */
+ /* do we have a FEC (860T/P or 852/859/866)? */
immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
@@ -114,6 +128,12 @@
putc ('\n');
+#ifdef DEBUG
+ if(clock != measure_gclk()) {
+ printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
+ }
+#endif
+
return 0;
}
@@ -316,7 +336,7 @@
volatile memctl8xx_t *memctl = &immap->im_memctl;
u32 cacheon = rd_ic_cst () & IDC_ENABLED;
-#ifdef CONFIG_IP860
+#ifdef CONFIG_IP86x
u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
#else
u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
@@ -363,7 +383,7 @@
volatile memctl8xx_t *memctl = &immap->im_memctl;
u32 cacheon = rd_dc_cst () & IDC_ENABLED;
-#ifdef CONFIG_IP860
+#ifdef CONFIG_IP86x
u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
#else
u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
@@ -462,8 +482,20 @@
if (immr->im_clkrst.car_sccr & SCCR_TBS) {
return (gd->cpu_clk / 16);
}
+#define PLPRCR_val(a) (((CFG_PLPRCR) & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+#ifdef CONFIG_MPC866_et_al
+ /* MFN
+ MFI + -------
+ MFD + 1
+ factor = -----------------
+ (PDF + 1) * 2^S
+ */
- factor = (((CFG_PLPRCR) & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT) + 1;
+ factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/
+ (PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
+#else
+ factor = PLPRCR_val(MF)+1;
+#endif
oscclk = gd->cpu_clk / factor;
diff --git a/cpu/mpc8xx/cpu_init.c b/cpu/mpc8xx/cpu_init.c
index 83ff66a..80f763d 100644
--- a/cpu/mpc8xx/cpu_init.c
+++ b/cpu/mpc8xx/cpu_init.c
@@ -145,6 +145,7 @@
defined(CONFIG_RPXCLASSIC) || \
defined(CONFIG_RPXLITE) || \
defined(CONFIG_SPD823TS) || \
+ defined(CONFIG_MPC86xADS) || \
(defined(CONFIG_MPC860T) && defined(CONFIG_FADS))
memctl->memc_br0 = CFG_BR0_PRELIM;
diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c
index 85ba6b2..8ac7842 100644
--- a/cpu/mpc8xx/fec.c
+++ b/cpu/mpc8xx/fec.c
@@ -217,7 +217,8 @@
volatile immap_t *immr = (immap_t *) CFG_IMMR;
volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
-#if defined(CONFIG_FADS) && defined(CONFIG_MPC860T)
+#if defined(CONFIG_FADS) && \
+ ( defined(CONFIG_MPC860T) || defined(CONFIG_MPC866_et_al) )
/* configure FADS for fast (FEC) ethernet, half-duplex */
/* The LXT970 needs about 50ms to recover from reset, so
* wait for it by discovering the PHY before leaving eth_init().
diff --git a/cpu/mpc8xx/interrupts.c b/cpu/mpc8xx/interrupts.c
index 8664826..8bc0a1af 100644
--- a/cpu/mpc8xx/interrupts.c
+++ b/cpu/mpc8xx/interrupts.c
@@ -334,7 +334,11 @@
/* Reset Timer Expired and Timers Interrupt Status */
immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
__asm__ ("nop");
+#ifdef CONFIG_MPC866_et_al
+ immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS;
+#else
immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS | PLPRCR_TMIST;
+#endif
/* Restore Decrementer Count */
set_dec (decrementer_count);
diff --git a/cpu/mpc8xx/scc.c b/cpu/mpc8xx/scc.c
index d711a63..e0fae5d 100644
--- a/cpu/mpc8xx/scc.c
+++ b/cpu/mpc8xx/scc.c
@@ -192,9 +192,9 @@
volatile immap_t *immr = (immap_t *)CFG_IMMR;
-#if defined(CONFIG_FADS)
-#if defined(CONFIG_MPC860T)
- /* The FADS860T doesn't use the MODEM_EN or DATA_VOICE signals. */
+#ifdef CONFIG_FADS
+#if defined(CONFIG_MPC86xADS) || defined(CONFIG_MPC860T)
+ /* The MPC86xADS/FADS860T don't use the MODEM_EN or DATA_VOICE signals. */
*((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
*((uint *) BCSR4) |= BCSR4_TFPLDL|BCSR4_TPSQEL;
*((uint *) BCSR1) &= ~BCSR1_ETHEN;
diff --git a/cpu/mpc8xx/serial.c b/cpu/mpc8xx/serial.c
index 81c0279..5ca4d90 100644
--- a/cpu/mpc8xx/serial.c
+++ b/cpu/mpc8xx/serial.c
@@ -68,6 +68,23 @@
#error "console not correctly defined"
#endif
+static void serial_setdivisor(volatile cpm8xx_t *cp)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ int divisor=gd->cpu_clk/16/gd->baudrate;
+
+ if(divisor/16>0x1000) {
+ /* bad divisor, assume 50Mhz clock and 9600 baud */
+ divisor=(50*1000*1000)/16/9600;
+ }
+
+ if(divisor<=0x1000) {
+ cp->cp_brgc1=((divisor-1)<<1) | CPM_BRG_EN;
+ } else {
+ cp->cp_brgc1=((divisor/16-1)<<1) | CPM_BRG_EN | CPM_BRG_DIV16;
+ }
+}
+
#if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
/*
@@ -229,8 +246,6 @@
void
serial_setbrg (void)
{
- DECLARE_GLOBAL_DATA_PTR;
-
volatile immap_t *im = (immap_t *)CFG_IMMR;
volatile cpm8xx_t *cp = &(im->im_cpm);
@@ -242,8 +257,7 @@
cp->cp_simode = 0x00000000;
- cp->cp_brgc1 =
- (((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
+ serial_setdivisor(cp);
}
#ifdef CONFIG_MODEM_SUPPORT
@@ -506,8 +520,6 @@
void
serial_setbrg (void)
{
- DECLARE_GLOBAL_DATA_PTR;
-
volatile immap_t *im = (immap_t *)CFG_IMMR;
volatile cpm8xx_t *cp = &(im->im_cpm);
@@ -518,10 +530,8 @@
*/
cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
- /* no |= needed, since BRG1 is 000 */
- cp->cp_brgc1 =
- (((gd->cpu_clk / 16 / gd->baudrate)-1) << 1) | CPM_BRG_EN;
+ serial_setdivisor(cp);
}
void
diff --git a/cpu/mpc8xx/speed.c b/cpu/mpc8xx/speed.c
index e1c3400..ae97d97 100644
--- a/cpu/mpc8xx/speed.c
+++ b/cpu/mpc8xx/speed.c
@@ -32,7 +32,6 @@
#define SPEED_PITC ((SPEED_PIT_COUNTS - 1) << PITC_SHIFT)
#define SPEED_PITC_INIT ((SPEED_PIT_COUNTS + 1) << PITC_SHIFT)
-#if !defined(CONFIG_8xx_GCLK_FREQ)
/* Access functions for the Machine State Register */
static __inline__ unsigned long get_msr(void)
{
@@ -46,7 +45,6 @@
{
asm volatile("mtmsr %0" : : "r" (msr));
}
-#endif
/* ------------------------------------------------------------------------- */
@@ -83,16 +81,20 @@
* CPU clock that is an even multiple of 0.1 MHz.
*/
-int get_clocks (void)
+unsigned long measure_gclk(void)
{
- DECLARE_GLOBAL_DATA_PTR;
-
volatile immap_t *immr = (immap_t *) CFG_IMMR;
-#ifndef CONFIG_8xx_GCLK_FREQ
volatile cpmtimer8xx_t *timerp = &immr->im_cpmtimer;
ulong timer2_val;
ulong msr_val;
+#ifdef CONFIG_MPC866_et_al
+ /* dont use OSCM, only use EXTCLK/512 */
+ immr->im_clkrst.car_sccr |= SCCR_RTSEL | SCCR_RTDIV;
+#else
+ immr->im_clkrst.car_sccr &= ~(SCCR_RTSEL | SCCR_RTDIV);
+#endif
+
/* Reset + Stop Timer 2, no cascading
*/
timerp->cpmt_tgcr &= ~(TGCR_CAS2 | TGCR_RST2);
@@ -158,10 +160,27 @@
timerp->cpmt_tgcr &= ~(TGCR_RST2 | TGCR_FRZ2 | TGCR_STP2);
immr->im_sit.sit_piscr &= ~PISCR_PTE;
+#ifdef CONFIG_MPC866_et_al
+ /* not using OSCM, using XIN, so scale appropriately */
+ return (((timer2_val + 2) / 4) * (CFG_8XX_XIN/512))/8192 * 100000L;
+#else
+ return ((timer2_val + 2) / 4) * 100000L; /* convert to Hz */
+#endif
+}
+
- gd->cpu_clk = ((timer2_val + 2) / 4) * 100000L; /* convert to Hz */
+/*
+ * 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)
+ * from above.
+ */
+int get_clocks (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ volatile immap_t *immr = (immap_t *) CFG_IMMR;
+#ifndef CONFIG_8xx_GCLK_FREQ
+ gd->cpu_clk = measure_gclk();
#else /* CONFIG_8xx_GCLK_FREQ */
-
/*
* If for some reason measuring the gclk frequency won't
* work, we return the hardwired value.