diff options
Diffstat (limited to 'cpu/mpc8xx')
-rw-r--r-- | cpu/mpc8xx/cpu.c | 104 | ||||
-rw-r--r-- | cpu/mpc8xx/cpu_init.c | 24 | ||||
-rw-r--r-- | cpu/mpc8xx/fec.c | 44 | ||||
-rw-r--r-- | cpu/mpc8xx/interrupts.c | 20 |
4 files changed, 132 insertions, 60 deletions
diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c index 2ef1321..3504422 100644 --- a/cpu/mpc8xx/cpu.c +++ b/cpu/mpc8xx/cpu.c @@ -45,24 +45,16 @@ static char *cpu_warning = "\n " \ #if ((defined(CONFIG_MPC86x) || defined(CONFIG_MPC855)) && \ !defined(CONFIG_MPC862)) +static int check_CPU (long clock, uint pvr, uint immr) +{ + char *id_str = # 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" + "PC855"; # elif defined(CONFIG_MPC860P) -# define ID_STR "PC860P" -# elif defined(CONFIG_MPC866T) -# define ID_STR "PC866T" + "PC860P"; # else -# define ID_STR "PC86x" /* unknown 86x chip */ + NULL; # endif - -static int check_CPU (long clock, uint pvr, uint immr) -{ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000); uint k, m; char buf[32]; @@ -78,12 +70,12 @@ static int check_CPU (long clock, uint pvr, uint immr) k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); m = 0; + /* + * Some boards use sockets so different CPUs can be used. + * We have to check chip version in run time. + */ 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 0x00020001: pre = 'P'; suf = ""; break; case 0x00030001: suf = ""; break; case 0x00120003: suf = "A"; break; case 0x00130003: suf = "A3"; break; @@ -98,18 +90,38 @@ static int check_CPU (long clock, uint pvr, uint immr) case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break; case 0x05010000: suf = "D3"; m = 1; break; case 0x05020000: suf = "D4"; m = 1; break; - case 0x08000003: suf = ""; m = 1; break; /* this value is not documented anywhere */ case 0x40000000: pre = 'P'; suf = "D"; m = 1; break; -#endif + /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */ + case 0x08000003: pre = 'M'; suf = ""; m = 1; + if (id_str == NULL) + id_str = +# if defined(CONFIG_MPC852T) + "PC852T"; +# elif defined(CONFIG_MPC859T) + "PC859T"; +# elif defined(CONFIG_MPC859DSL) + "PC859DSL"; +# elif defined(CONFIG_MPC866T) + "PC866T"; +# else + "PC866x"; /* Unknown chip from MPC866 family */ +# endif + break; + case 0x09000000: pre = 'M'; mid = suf = ""; m = 1; + if (id_str == NULL) + id_str = "PC885"; /* 870/875/880/885 */ + break; default: suf = NULL; break; } + if (id_str == NULL) + id_str = "PC86x"; /* Unknown 86x chip */ if (suf) - printf ("%c" ID_STR "%sZPnn%s", pre, mid, suf); + printf ("%c%s%sZPnn%s", pre, id_str, mid, suf); else - printf ("unknown M" ID_STR " (0x%08x)", k); + printf ("unknown M%s (0x%08x)", id_str, k); printf (" at %s MHz:", strmhz (buf, clock)); @@ -471,36 +483,46 @@ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* * Get timebase clock frequency (like cpu_clk in Hz) * - * See table 15-5 pp. 15-16, and SCCR[RTSEL] pp. 15-27. + * See sections 14.2 and 14.6 of the User's Manual */ unsigned long get_tbclk (void) { DECLARE_GLOBAL_DATA_PTR; - volatile immap_t *immr = (volatile immap_t *) CFG_IMMR; - ulong oscclk, factor; + uint immr = get_immr (0); /* Return full IMMR contents */ + volatile immap_t *immap = (volatile immap_t *)(immr & 0xFFFF0000); + ulong oscclk, factor, pll; - if (immr->im_clkrst.car_sccr & SCCR_TBS) { + if (immap->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 = (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 + pll = immap->im_clkrst.car_plprcr; + +#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT) + + /* + * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication + * factor is calculated as follows: + * + * MFN + * MFI + ------- + * MFD + 1 + * factor = ----------------- + * (PDF + 1) * 2^S + * + * For older chips, it's just MF field of PLPRCR plus one. + */ + if ((immr & 0xFFFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */ + 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; + } oscclk = gd->cpu_clk / factor; - if ((immr->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) { + if ((immap->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) { return (oscclk / 4); } return (oscclk / 16); diff --git a/cpu/mpc8xx/cpu_init.c b/cpu/mpc8xx/cpu_init.c index 8f06dd1..cbf2126 100644 --- a/cpu/mpc8xx/cpu_init.c +++ b/cpu/mpc8xx/cpu_init.c @@ -42,6 +42,7 @@ void cpu_init_f (volatile immap_t * immr) { #ifndef CONFIG_MBX volatile memctl8xx_t *memctl = &immr->im_memctl; + ulong mfmask; #endif ulong reg; @@ -86,16 +87,23 @@ void cpu_init_f (volatile immap_t * immr) /* If CFG_PLPRCR (set in the various *_config.h files) tries to * set the MF field, then just copy CFG_PLPRCR over car_plprcr, - * otherwise OR in CFG_PLPRCR so we do not change the currentMF + * otherwise OR in CFG_PLPRCR so we do not change the current MF * field value. + * + * For newer (starting MPC866) chips PLPRCR layout is different. */ -#if ((CFG_PLPRCR & PLPRCR_MF_MSK) != 0) - reg = CFG_PLPRCR; /* reset control bits */ -#else - reg = immr->im_clkrst.car_plprcr; - reg &= PLPRCR_MF_MSK; /* isolate MF field */ - reg |= CFG_PLPRCR; /* reset control bits */ -#endif + if (get_immr(0xFFFF) >= MPC8xx_NEW_CLK) + mfmask = PLPRCR_MFACT_MSK; + else + mfmask = PLPRCR_MF_MSK; + + if ((CFG_PLPRCR & mfmask) != 0) + reg = CFG_PLPRCR; /* reset control bits */ + else { + reg = immr->im_clkrst.car_plprcr; + reg &= mfmask; /* isolate MF-related fields */ + reg |= CFG_PLPRCR; /* reset control bits */ + } immr->im_clkrst.car_plprcr = reg; /* diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index 6b579c9..811ac79 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -217,8 +217,10 @@ static int fec_init(struct eth_device* dev, bd_t * bd) volatile immap_t *immr = (immap_t *) CFG_IMMR; volatile fec_t *fecp = &(immr->im_cpm.cp_fec); -#if defined(CONFIG_FADS) && \ - ( defined(CONFIG_MPC860T) || defined(CONFIG_MPC866_et_al) ) +#if defined(CONFIG_FADS) /* FADS family uses FPGA (BCSR) to control PHYs */ +#if defined(CONFIG_DUET_ADS) + *(vu_char *)BCSR5 &= ~(BCSR5_MII1_EN | BCSR5_MII1_RST); +#else /* 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(). @@ -234,7 +236,8 @@ static int fec_init(struct eth_device* dev, bd_t * bd) *bcsr4 |= BCSR4_FETHRST; udelay (10); } -#endif +#endif /* CONFIG_DUET_ADS */ +#endif /* CONFIG_FADS */ /* Whack a reset. * A delay is required between a reset of the FEC block and * initialization of other FEC registers because the reset takes @@ -350,7 +353,20 @@ static int fec_init(struct eth_device* dev, bd_t * bd) */ fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; -#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) +#if defined(CONFIG_DUET) /* MPC87x/88x have got 2 FECs and different pinout */ + immr->im_ioport.iop_papar |= 0xf830; + immr->im_ioport.iop_padir |= 0x0830; + immr->im_ioport.iop_padir &= ~0xf000; + immr->im_cpm.cp_pbpar |= 0x00001001; + immr->im_cpm.cp_pbdir &= ~0x00001001; + immr->im_ioport.iop_pcpar |= 0x000c; + immr->im_ioport.iop_pcdir &= ~0x000c; + immr->im_ioport.iop_pdpar |= 0x0080; + immr->im_ioport.iop_pddir &= ~0x0080; + immr->im_cpm.cp_pepar |= 0x00000003; + immr->im_cpm.cp_pedir |= 0x00000003; + immr->im_cpm.cp_peso &= ~0x00000003; +#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) /* Configure all of port D for MII. */ immr->im_ioport.iop_pdpar = 0x1fff; @@ -465,7 +481,7 @@ static uint phytype; #define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */ #define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */ #define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */ - +#define PHY_ID_DM9161 0x0181B880 /* Davicom DM9161 */ /* send command to phy using mii, wait for result */ static uint @@ -541,6 +557,9 @@ mii_discover_phy(void) case PHY_ID_LSI80225B: printf("LSI L80225/B\n"); break; + case PHY_ID_DM9161: + printf("Davicom DM9161\n"); + break; default: printf("0x%08x\n", phytype); break; @@ -614,7 +633,20 @@ void mii_init (void) */ fecp->fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1; -#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) +#if defined(CONFIG_DUET) /* MPC87x/88x have got 2 FECs and different pinout */ + immr->im_ioport.iop_papar |= 0xf830; + immr->im_ioport.iop_padir |= 0x0830; + immr->im_ioport.iop_padir &= ~0xf000; + immr->im_cpm.cp_pbpar |= 0x00001001; + immr->im_cpm.cp_pbdir &= ~0x00001001; + immr->im_ioport.iop_pcpar |= 0x000c; + immr->im_ioport.iop_pcdir &= ~0x000c; + immr->im_ioport.iop_pdpar |= 0x0080; + immr->im_ioport.iop_pddir &= ~0x0080; + immr->im_cpm.cp_pepar |= 0x00000003; + immr->im_cpm.cp_pedir |= 0x00000003; + immr->im_cpm.cp_peso &= ~0x00000003; +#elif !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) /* Configure all of port D for MII. */ immr->im_ioport.iop_pdpar = 0x1fff; diff --git a/cpu/mpc8xx/interrupts.c b/cpu/mpc8xx/interrupts.c index 558dc09..20e7012 100644 --- a/cpu/mpc8xx/interrupts.c +++ b/cpu/mpc8xx/interrupts.c @@ -274,11 +274,21 @@ void timer_interrupt_cpu (struct pt_regs *regs) /* 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 + /* + Clear TEXPS (and TMIST on older chips). SPLSS (on older + chips) is cleared too. + + Bitwise OR is a read-modify-write operation so ALL bits + which are cleared by writing `1' would be cleared by + operations like + + immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS; + + The same can be achieved by simple writing of the PLPRCR + to itself. If a bit value should be preserved, read the + register, ZERO the bit and write, not OR, the result back. + */ + immr->im_clkrst.car_plprcr = immr->im_clkrst.car_plprcr; } /************************************************************************/ |