diff options
author | Jon Loeliger <jdl@freescale.com> | 2006-06-07 08:49:46 -0500 |
---|---|---|
committer | Jon Loeliger <jdl@freescale.com> | 2006-06-07 08:49:46 -0500 |
commit | a941b832411ef99351a42be23ff3319643dcc1a4 (patch) | |
tree | 1cdaa7e1e82679a5acf20676960df2b0d91d94b2 /cpu | |
parent | 72ed528a948b151e7be5ce03ed3d2b88a229dd0a (diff) | |
parent | c83ae9ea6d93abbe751bf8a3396236a084e56f87 (diff) | |
download | u-boot-imx-a941b832411ef99351a42be23ff3319643dcc1a4.zip u-boot-imx-a941b832411ef99351a42be23ff3319643dcc1a4.tar.gz u-boot-imx-a941b832411ef99351a42be23ff3319643dcc1a4.tar.bz2 |
Merge branch 'mpc86xx'
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/mpc86xx/Makefile | 4 | ||||
-rw-r--r-- | cpu/mpc86xx/cache.S | 28 | ||||
-rw-r--r-- | cpu/mpc86xx/config.mk | 4 | ||||
-rw-r--r-- | cpu/mpc86xx/cpu.c | 402 | ||||
-rw-r--r-- | cpu/mpc86xx/cpu_init.c | 11 | ||||
-rw-r--r-- | cpu/mpc86xx/i2c.c | 6 | ||||
-rw-r--r-- | cpu/mpc86xx/interrupts.c | 42 | ||||
-rw-r--r-- | cpu/mpc86xx/spd_sdram.c | 617 | ||||
-rw-r--r-- | cpu/mpc86xx/speed.c | 69 | ||||
-rw-r--r-- | cpu/mpc86xx/start.S | 15 |
10 files changed, 582 insertions, 616 deletions
diff --git a/cpu/mpc86xx/Makefile b/cpu/mpc86xx/Makefile index 0dd099d..ab6255a 100644 --- a/cpu/mpc86xx/Makefile +++ b/cpu/mpc86xx/Makefile @@ -3,7 +3,7 @@ # Xianghua Xiao,X.Xiao@motorola.com # # (C) Copyright 2004 Freescale Semiconductor. (MC86xx Port) -# Jeff Brown (Jeffrey@freescale.com) +# Jeff Brown # See file CREDITS for list of people who contributed to this # project. # @@ -30,7 +30,7 @@ LIB = lib$(CPU).a START = start.o #resetvec.o ASOBJS = cache.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \ - pci.o i2c.o spd_sdram.o + pci.o i2c.o spd_sdram.o OBJS = $(COBJS) all: .depend $(START) $(ASOBJS) $(LIB) diff --git a/cpu/mpc86xx/cache.S b/cpu/mpc86xx/cache.S index 75186b1..f316b3e 100644 --- a/cpu/mpc86xx/cache.S +++ b/cpu/mpc86xx/cache.S @@ -28,7 +28,7 @@ * Most of this code is taken from 74xx_7xx/cache.S * and then cleaned up a bit */ - + /* * Invalidate L1 instruction cache. */ @@ -316,24 +316,30 @@ _GLOBAL(dcache_status) blr /* - * Invalidate L2 cache using L2I and polling L2IP + * Invalidate L2 cache using L2I, assume L2 is enabled */ _GLOBAL(l2cache_invalidate) - sync - oris r3, r3, L2CR_L2I@h + mfspr r3, l2cr + rlwinm. r3, r3, 0, 0, 0 + beq 1f + + mfspr r3, l2cr + rlwinm r3, r3, 0, 1, 31 + +#ifdef CONFIG_ALTIVEC + dssall +#endif sync mtspr l2cr, r3 sync +1: mfspr r3, l2cr + oris r3, r3, L2CR_L2I@h + mtspr l2cr, r3 + invl2: mfspr r3, l2cr - andi. r3, r3, L2CR_L2IP + andi. r3, r3, L2CR_L2I@h bne invl2 - /* turn off the global invalidate bit */ - mfspr r3, l2cr - rlwinm r3, r3, 0, 11, 9 - sync - mtspr l2cr, r3 - sync blr /* diff --git a/cpu/mpc86xx/config.mk b/cpu/mpc86xx/config.mk index 4ef7ace..3c54f4a 100644 --- a/cpu/mpc86xx/config.mk +++ b/cpu/mpc86xx/config.mk @@ -1,6 +1,6 @@ # # (C) Copyright 2004 Freescale Semiconductor. -# Jeff Brown <jeffrey@freescale.com> +# Jeff Brown # # See file CREDITS for list of people who contributed to this # project. @@ -23,4 +23,4 @@ PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -PLATFORM_CPPFLAGS += -DCONFIG_MPC86xx -ffixed-r2 -ffixed-r29 -mstring
\ No newline at end of file +PLATFORM_CPPFLAGS += -DCONFIG_MPC86xx -ffixed-r2 -ffixed-r29 -mstring diff --git a/cpu/mpc86xx/cpu.c b/cpu/mpc86xx/cpu.c index 36da777..fc77d99 100644 --- a/cpu/mpc86xx/cpu.c +++ b/cpu/mpc86xx/cpu.c @@ -1,6 +1,6 @@ /* - * Copyright 2004 Freescale Semiconductor - * Jeff Brown (jeffrey@freescale.com) + * Copyright 2006 Freescale Semiconductor + * Jeff Brown * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) * * See file CREDITS for list of people who contributed to this @@ -32,29 +32,10 @@ #include <ft_build.h> #endif -extern unsigned long get_board_sys_clk(ulong dummy); - - -static __inline__ unsigned long get_dbat3u (void) -{ - unsigned long dbat3u; - asm volatile("mfspr %0, 542" : "=r" (dbat3u) :); - return dbat3u; -} - -static __inline__ unsigned long get_dbat3l (void) -{ - unsigned long dbat3l; - asm volatile("mfspr %0, 543" : "=r" (dbat3l) :); - return dbat3l; -} - -static __inline__ unsigned long get_msr (void) -{ - unsigned long msr; - asm volatile("mfmsr %0" : "=r" (msr) :); - return msr; -} +#ifdef CONFIG_MPC8641HPCN +extern void mpc8641_reset_board(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[]); +#endif int checkcpu (void) @@ -74,8 +55,7 @@ int checkcpu (void) minor = PVR_MIN(pvr); puts("CPU:\n"); - - printf(" Core: "); + puts(" Core: "); switch (ver) { case PVR_VER(PVR_86xx): @@ -131,22 +111,19 @@ int checkcpu (void) printf(" LBC: unknown (lcrr: 0x%08x)\n", lcrr); } - printf(" L2: "); - if (get_l2cr() & 0x80000000) - printf("Enabled\n"); - else - printf("Disabled\n"); + puts(" L2: "); + if (get_l2cr() & 0x80000000) + puts("Enabled\n"); + else + puts("Disabled\n"); return 0; } -/* -------------------------------------------------------------------- */ - static inline void soft_restart(unsigned long addr) { - #ifndef CONFIG_MPC8641HPCN /* SRR0 has system reset vector, SRR1 has default MSR value */ @@ -158,283 +135,25 @@ soft_restart(unsigned long addr) __asm__ __volatile__ ("rfi"); #else /* CONFIG_MPC8641HPCN */ - out8(PIXIS_BASE+PIXIS_RST,0); -#endif /* !CONFIG_MPC8641HPCN */ - while(1); /* not reached */ -} - - - -#ifdef CONFIG_MPC8641HPCN - -int set_px_sysclk(ulong sysclk) -{ - u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux,tmp; - - /* Per table 27, page 58 of MPC8641HPCN spec*/ - switch(sysclk) - { - case 33: - sysclk_s = 0x04; - sysclk_r = 0x04; - sysclk_v = 0x07; - sysclk_aux = 0x00; - break; - case 40: - sysclk_s = 0x01; - sysclk_r = 0x1F; - sysclk_v = 0x20; - sysclk_aux = 0x01; - break; - case 50: - sysclk_s = 0x01; - sysclk_r = 0x1F; - sysclk_v = 0x2A; - sysclk_aux = 0x02; - break; - case 66: - sysclk_s = 0x01; - sysclk_r = 0x04; - sysclk_v = 0x04; - sysclk_aux = 0x03; - break; - case 83: - sysclk_s = 0x01; - sysclk_r = 0x1F; - sysclk_v = 0x4B; - sysclk_aux = 0x04; - break; - case 100: - sysclk_s = 0x01; - sysclk_r = 0x1F; - sysclk_v = 0x5C; - sysclk_aux = 0x05; - break; - case 134: - sysclk_s = 0x06; - sysclk_r = 0x1F; - sysclk_v = 0x3B; - sysclk_aux = 0x06; - break; - case 166: - sysclk_s = 0x06; - sysclk_r = 0x1F; - sysclk_v = 0x4B; - sysclk_aux = 0x07; - break; - default: - printf("Unsupported SYSCLK frequency.\n"); - return 0; - } - - vclkh = (sysclk_s << 5) | sysclk_r ; - vclkl = sysclk_v; - out8(PIXIS_BASE+PIXIS_VCLKH,vclkh); - out8(PIXIS_BASE+PIXIS_VCLKL,vclkl); - - out8(PIXIS_BASE+PIXIS_AUX,sysclk_aux); - - return 1; -} - -int set_px_mpxpll(ulong mpxpll) -{ - u8 tmp; - u8 val; - switch(mpxpll) - { - case 2: - case 4: - case 6: - case 8: - case 10: - case 12: - case 14: - case 16: - val = (u8)mpxpll; - break; - default: - printf("Unsupported MPXPLL ratio.\n"); - return 0; - } - - tmp = in8(PIXIS_BASE+PIXIS_VSPEED1); - tmp = (tmp & 0xF0) | (val & 0x0F); - out8(PIXIS_BASE+PIXIS_VSPEED1,tmp); - - return 1; -} -int set_px_corepll(ulong corepll) -{ - u8 tmp; - u8 val; - - switch ((int)corepll) { - case 20: - val = 0x08; - break; - case 25: - val = 0x0C; - break; - case 30: - val = 0x10; - break; - case 35: - val = 0x1C; - break; - case 40: - val = 0x14; - break; - case 45: - val = 0x0E; - break; - default: - printf("Unsupported COREPLL ratio.\n"); - return 0; - } - - tmp = in8(PIXIS_BASE+PIXIS_VSPEED0); - tmp = (tmp & 0xE0) | (val & 0x1F); - out8(PIXIS_BASE+PIXIS_VSPEED0,tmp); - - return 1; -} - -void read_from_px_regs(int set) -{ - u8 tmp, mask = 0x1C; - tmp = in8(PIXIS_BASE+PIXIS_VCFGEN0); - if (set) - tmp = tmp | mask; - else - tmp = tmp & ~mask; - out8(PIXIS_BASE+PIXIS_VCFGEN0,tmp); -} - -void read_from_px_regs_altbank(int set) -{ - u8 tmp, mask = 0x04; - tmp = in8(PIXIS_BASE+PIXIS_VCFGEN1); - if (set) - tmp = tmp | mask; - else - tmp = tmp & ~mask; - out8(PIXIS_BASE+PIXIS_VCFGEN1,tmp); -} - -void set_altbank(void) -{ - u8 tmp; - tmp = in8(PIXIS_BASE+PIXIS_VBOOT); - tmp ^= 0x40; - out8(PIXIS_BASE+PIXIS_VBOOT,tmp); - } - - -void set_px_go(void) -{ - u8 tmp; - tmp = in8(PIXIS_BASE+PIXIS_VCTL); - tmp = tmp & 0x1E; - out8(PIXIS_BASE+PIXIS_VCTL,tmp); - tmp = in8(PIXIS_BASE+PIXIS_VCTL); - tmp = tmp | 0x01; - out8(PIXIS_BASE+PIXIS_VCTL,tmp); -} + out8(PIXIS_BASE + PIXIS_RST, 0); -void set_px_go_with_watchdog(void) -{ - u8 tmp; - tmp = in8(PIXIS_BASE+PIXIS_VCTL); - tmp = tmp & 0x1E; - out8(PIXIS_BASE+PIXIS_VCTL,tmp); - tmp = in8(PIXIS_BASE+PIXIS_VCTL); - tmp = tmp | 0x09; - out8(PIXIS_BASE+PIXIS_VCTL,tmp); -} - -/* This function takes the non-integral cpu:mpx pll ratio - * and converts it to an integer that can be used to assign - * FPGA register values. - * input: strptr i.e. argv[2] -*/ - -ulong strfractoint(uchar *strptr) -{ - int i,j,retval,intarr_len=0, decarr_len=0, mulconst, no_dec=0; - ulong intval =0, decval=0; - uchar intarr[3], decarr[3]; - - /* Assign the integer part to intarr[] - * If there is no decimal point i.e. - * if the ratio is an integral value - * simply create the intarr. - */ - i=0; - while(strptr[i] != 46) - { - if(strptr[i] == 0) - { - no_dec = 1; - break; /* Break from loop once the end of string is reached */ - } - - intarr[i] = strptr[i]; - i++; - } - - intarr_len = i; /* Assign length of integer part to intarr_len*/ - intarr[i] = '\0'; /* */ - - if(no_dec) - { - mulconst=10; /* Currently needed only for single digit corepll ratios */ - decval = 0; - } - else - { - j=0; - i++; /* Skipping the decimal point */ - while ((strptr[i] > 47) && (strptr[i] < 58)) - { - decarr[j] = strptr[i]; - i++; - j++; - } - - decarr_len = j; - decarr[j] = '\0'; - - mulconst=1; - for(i=0; i<decarr_len;i++) - mulconst = mulconst*10; - decval = simple_strtoul(decarr,NULL,10); - } - - intval = simple_strtoul(intarr,NULL,10); - intval = intval*mulconst; - - retval = intval+decval; - - return retval; +#endif /* !CONFIG_MPC8641HPCN */ + while(1); /* not reached */ } -#endif /* CONFIG_MPC8641HPCN */ - - -/* no generic way to do board reset. simply call soft_reset. */ +/* + * No generic way to do board reset. Simply call soft_reset. + */ void -do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - char cmd; - ulong addr, val; - ulong corepll; +#ifndef CONFIG_MPC8641HPCN #ifdef CFG_RESET_ADDRESS - addr = CFG_RESET_ADDRESS; + ulong addr = CFG_RESET_ADDRESS; #else /* * note: when CFG_MONITOR_BASE points to a RAM address, @@ -442,11 +161,9 @@ do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * address. Better pick an address known to be invalid on your * system and assign it to CFG_RESET_ADDRESS. */ - addr = CFG_MONITOR_BASE - sizeof (ulong); + ulong addr = CFG_MONITOR_BASE - sizeof(ulong); #endif -#ifndef CONFIG_MPC8641HPCN - /* flush and disable I/D cache */ __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); @@ -460,81 +177,11 @@ do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) __asm__ __volatile__ ("isync"); __asm__ __volatile__ ("sync"); - soft_restart(addr); + soft_restart(addr); #else /* CONFIG_MPC8641HPCN */ - if (argc > 1) { - cmd = argv[1][1]; - switch(cmd) { - case 'f': /* reset with frequency changed */ - if (argc < 5) - goto my_usage; - read_from_px_regs(0); - - val = set_px_sysclk(simple_strtoul(argv[2],NULL,10)); - - corepll = strfractoint(argv[3]); - val = val + set_px_corepll(corepll); - val = val + set_px_mpxpll(simple_strtoul(argv[4], - NULL, 10)); - if (val == 3) { - printf("Setting registers VCFGEN0 and VCTL\n"); - read_from_px_regs(1); - printf("Resetting board with values from VSPEED0, VSPEED1, VCLKH, and VCLKL ....\n"); - set_px_go(); - } else - goto my_usage; - - while (1); /* Not reached */ - - case 'l': - if (argv[2][1] == 'f') { - read_from_px_regs(0); - read_from_px_regs_altbank(0); - /* reset with frequency changed */ - val = set_px_sysclk(simple_strtoul(argv[3],NULL,10)); - - corepll = strfractoint(argv[4]); - val = val + set_px_corepll(corepll); - val = val + set_px_mpxpll(simple_strtoul(argv[5],NULL,10)); - if (val == 3) { - printf("Setting registers VCFGEN0, VCFGEN1, VBOOT, and VCTL\n"); - set_altbank(); - read_from_px_regs(1); - read_from_px_regs_altbank(1); - printf("Enabling watchdog timer on the FPGA and resetting board with values from VSPEED0, VSPEED1, VCLKH, and VCLKL to boot from the other bank ....\n"); - set_px_go_with_watchdog(); - } else - goto my_usage; - - while(1); /* Not reached */ - } else { - /* Reset from next bank without changing frequencies */ - read_from_px_regs(0); - read_from_px_regs_altbank(0); - if(argc > 2) - goto my_usage; - printf("Setting registers VCFGEN1, VBOOT, and VCTL\n"); - set_altbank(); - read_from_px_regs_altbank(1); - printf("Enabling watchdog timer on the FPGA and resetting board to boot from the other bank....\n"); - set_px_go_with_watchdog(); - while(1); /* Not reached */ - } - - default: - goto my_usage; - } - -my_usage: - printf("\nUsage: reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"); - printf(" reset altbank [cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>]\n"); - printf("For example: reset cf 40 2.5 10\n"); - printf("See MPC8641HPCN Design Workbook for valid values of command line parameters.\n"); - return; - } else - out8(PIXIS_BASE+PIXIS_RST,0); + mpc8641_reset_board(cmdtp, flag, argc, argv); #endif /* !CONFIG_MPC8641HPCN */ @@ -571,7 +218,6 @@ void dma_init(void) dma->satr0 = 0x00040000; dma->datr0 = 0x00040000; asm("sync; isync"); - return; } uint dma_check(void) diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c index c816c18..93b7338 100644 --- a/cpu/mpc86xx/cpu_init.c +++ b/cpu/mpc86xx/cpu_init.c @@ -1,6 +1,6 @@ /* * Copyright 2004 Freescale Semiconductor. - * Jeff Brown (jeffrey@freescale.com) + * Jeff Brown * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) * * See file CREDITS for list of people who contributed to this @@ -106,15 +106,6 @@ void cpu_init_f(void) /* enable SYNCBE | ABE bits in HID1 */ set_hid1(get_hid1() | 0x00000C00); - - /* Since the bats have been set up at this point and - * the local bus registers have been initialized, we - * turn on the WDEN bit in PIXIS_VCTL - */ -/* val = in8(PIXIS_BASE+PIXIS_VCTL); */ - /* Set the WDEN */ -/* val |= 0x08; */ -/* out8(PIXIS_BASE+PIXIS_VCTL,val); */ } /* diff --git a/cpu/mpc86xx/i2c.c b/cpu/mpc86xx/i2c.c index f2b4b0f..b3ac848 100644 --- a/cpu/mpc86xx/i2c.c +++ b/cpu/mpc86xx/i2c.c @@ -7,7 +7,7 @@ * Gleb Natapov <gnatapov@mrv.com> * Some bits are taken from linux driver writen by adrian@humboldt.co.uk * - * Modified for MPC86xx by Jeff Brown (jeffrey@freescale.com) + * Modified for MPC86xx by Jeff Brown * * Hardware I2C driver for MPC107 PCI bridge. * @@ -207,7 +207,7 @@ i2c_read (u8 dev, uint addr, int alen, u8 *data, int length) i = __i2c_read(data, length); - exit: +exit: writeb(MPC86xx_I2CCR_MEN, I2CCCR); return !(i == length); @@ -230,7 +230,7 @@ i2c_write (u8 dev, uint addr, int alen, u8 *data, int length) i = __i2c_write(data, length); - exit: +exit: writeb(MPC86xx_I2CCR_MEN, I2CCCR); return !(i == length); diff --git a/cpu/mpc86xx/interrupts.c b/cpu/mpc86xx/interrupts.c index b5cd439..a8bcb98 100644 --- a/cpu/mpc86xx/interrupts.c +++ b/cpu/mpc86xx/interrupts.c @@ -9,7 +9,7 @@ * Xianghua Xiao (X.Xiao@motorola.com) * * (C) Copyright 2004 Freescale Semiconductor. (MPC86xx Port) - * Jeff Brown (Jeffrey@freescale.com) + * Jeff Brown * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) * * See file CREDITS for list of people who contributed to this @@ -37,11 +37,10 @@ #include <asm/processor.h> #include <ppc_asm.tmpl> -unsigned long decrementer_count; /* count value for 1e6/HZ microseconds */ - - +unsigned long decrementer_count; /* count value for 1e6/HZ microseconds */ unsigned long timestamp; + static __inline__ unsigned long get_msr (void) { unsigned long msr; @@ -75,7 +74,7 @@ static __inline__ void set_dec (unsigned long val) /* interrupt is not supported yet */ int interrupt_init_cpu (unsigned *decrementer_count) { - return 0; + return 0; } @@ -89,14 +88,14 @@ int interrupt_init (void) if (ret) return ret; - decrementer_count = get_tbclk()/CFG_HZ; - debug("interrupt init: tbclk() = %d MHz, decrementer_count = %d\n", (get_tbclk()/1000000), decrementer_count); + decrementer_count = get_tbclk()/CFG_HZ; + debug("interrupt init: tbclk() = %d MHz, decrementer_count = %d\n", (get_tbclk()/1000000), decrementer_count); - set_dec (decrementer_count); + set_dec (decrementer_count); set_msr (get_msr () | MSR_EE); - debug("MSR = 0x%08lx, Decrementer reg = 0x%08lx\n", get_msr(), get_dec()); + debug("MSR = 0x%08lx, Decrementer reg = 0x%08lx\n", get_msr(), get_dec()); return 0; } @@ -119,7 +118,7 @@ int disable_interrupts (void) void increment_timestamp(void) { - timestamp++; + timestamp++; } /* @@ -136,15 +135,15 @@ timer_interrupt_cpu (struct pt_regs *regs) void timer_interrupt (struct pt_regs *regs) { - /* call cpu specific function from $(CPU)/interrupts.c */ - timer_interrupt_cpu (regs); + /* call cpu specific function from $(CPU)/interrupts.c */ + timer_interrupt_cpu (regs); - timestamp++; + timestamp++; - ppcDcbf(×tamp); + ppcDcbf(×tamp); - /* Restore Decrementer Count */ - set_dec (decrementer_count); + /* Restore Decrementer Count */ + set_dec (decrementer_count); #if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG) if ((timestamp % (CFG_WATCHDOG_FREQ)) == 0) @@ -164,17 +163,17 @@ void timer_interrupt (struct pt_regs *regs) void reset_timer (void) { - timestamp = 0; + timestamp = 0; } ulong get_timer (ulong base) { - return timestamp - base; + return timestamp - base; } void set_timer (ulong t) { - timestamp = t; + timestamp = t; } /* @@ -192,11 +191,8 @@ irq_free_handler(int vec) } - -/******************************************************************************* - * +/* * irqinfo - print information about PCI devices,not implemented. - * */ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) diff --git a/cpu/mpc86xx/spd_sdram.c b/cpu/mpc86xx/spd_sdram.c index 9ce31d7..f30bbbd 100644 --- a/cpu/mpc86xx/spd_sdram.c +++ b/cpu/mpc86xx/spd_sdram.c @@ -42,6 +42,15 @@ extern int dma_xfer(void *dest, uint count, void *src); #endif /* + * Only one of the following three should be 1; others should be 0 + * By default the cache line interleaving is selected if + * the CONFIG_DDR_INTERLEAVE flag is defined in MPC8641HPCN.h + */ +#define CFG_PAGE_INTERLEAVING 0 +#define CFG_BANK_INTERLEAVING 0 +#define CFG_SUPER_BANK_INTERLEAVING 0 + +/* * Convert picoseconds into clock cycles (rounding up if needed). */ @@ -144,10 +153,11 @@ convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) long int -spd_sdram(void) +spd_init(unsigned char i2c_address, unsigned int ddr_num, + unsigned int dimm_num, unsigned int start_addr) { volatile immap_t *immap = (immap_t *)CFG_IMMR; - volatile ccsr_ddr_t *ddr1 = &immap->im_ddr1; + volatile ccsr_ddr_t *ddr; volatile ccsr_gur_t *gur = &immap->im_gur; spd_eeprom_t spd; unsigned int n_ranks; @@ -175,28 +185,41 @@ spd_sdram(void) unsigned int mode_caslat; unsigned char sdram_type; unsigned char d_init; + unsigned int law_size; + volatile ccsr_local_mcm_t *mcm = &immap->im_local_mcm; - - unsigned int law_size; - volatile ccsr_local_mcm_t *mcm = &immap->im_local_mcm; + if (ddr_num == 1) + ddr = &immap->im_ddr1; + else + ddr = &immap->im_ddr2; /* * Read SPD information. */ - CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) &spd, sizeof(spd)); + debug("Performing SPD read at I2C address 0x%02lx\n",i2c_address); + memset((void *)&spd, 0, sizeof(spd)); + CFG_READ_SPD(i2c_address, 0, 1, (uchar *) &spd, sizeof(spd)); /* * Check for supported memory module types. */ if (spd.mem_type != SPD_MEMTYPE_DDR && spd.mem_type != SPD_MEMTYPE_DDR2) { - printf("Unable to locate DDR I or DDR II module.\n" - " Fundamental memory type is 0x%0x\n", - spd.mem_type); + debug("Warning: Unable to locate DDR I or DDR II module for DIMM %d of DDR controller %d.\n" + " Fundamental memory type is 0x%0x\n", + dimm_num, + ddr_num, + spd.mem_type); return 0; } + debug("\nFound memory of type 0x%02lx ", spd.mem_type); + if (spd.mem_type == SPD_MEMTYPE_DDR) + debug("DDR I\n"); + else + debug("DDR II\n"); + /* * These test gloss over DDR I and II differences in interpretation * of bytes 3 and 4, but irrelevantly. Multiple asymmetric banks @@ -253,11 +276,7 @@ spd_sdram(void) */ rank_density = compute_banksize(spd.mem_type, spd.row_dens); - - /* - * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg - */ - ddr1->cs0_bnds = (rank_density >> 24) - 1; + debug("Start address for this controller is 0x%08lx\n", start_addr); /* * ODT configuration recommendation from DDR Controller Chapter. @@ -268,30 +287,133 @@ spd_sdram(void) odt_wr_cfg = 1; /* Assert ODT on writes to CS0 */ } - ddr1->cs0_config = ( 1 << 31 - | (odt_rd_cfg << 20) - | (odt_wr_cfg << 16) - | (spd.nrow_addr - 12) << 8 - | (spd.ncol_addr - 8) ); - debug("\n"); - debug("DDR: cs0_bnds = 0x%08x\n", ddr1->cs0_bnds); - debug("DDR: cs0_config = 0x%08x\n", ddr1->cs0_config); +#ifdef CONFIG_DDR_INTERLEAVE +#ifdef CONFIG_MPC8641HPCN + if (dimm_num != 1) { + printf("For interleaving memory on HPCN, need to use DIMM 1 for DDR Controller %d !\n", ddr_num); + return 0; + } else { + /* + * Since interleaved memory only uses CS0, the + * memory sticks have to be identical in size and quantity + * of ranks. That essentially gives double the size on + * one rank, i.e on CS0 for both controllers put together. + * Confirm this??? + */ + rank_density *= 2; - if (n_ranks == 2) { /* - * Eg: Bounds: 0x0f00_0000 to 0x1e0000_0000, second 256 Meg + * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg + */ + start_addr = 0; + ddr->cs0_bnds = (start_addr >> 8) + | (((start_addr + rank_density - 1) >> 24)); + /* + * Default interleaving mode to cache-line interleaving. */ - ddr1->cs1_bnds = ( (rank_density >> 8) - | ((rank_density >> (24 - 1)) - 1) ); - ddr1->cs1_config = ( 1<<31 + ddr->cs0_config = ( 1 << 31 +#if (CFG_PAGE_INTERLEAVING == 1) + | (PAGE_INTERLEAVING) +#elif (CFG_BANK_INTERLEAVING == 1) + | (BANK_INTERLEAVING) +#elif (CFG_SUPER_BANK_INTERLEAVING == 1) + | (SUPER_BANK_INTERLEAVING) +#else + | (CACHE_LINE_INTERLEAVING) +#endif | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); - debug("DDR: cs1_bnds = 0x%08x\n", ddr1->cs1_bnds); - debug("DDR: cs1_config = 0x%08x\n", ddr1->cs1_config); + + debug("DDR: cs0_bnds = 0x%08x\n", ddr->cs0_bnds); + debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config); + + /* + * Adjustment for dual rank memory to get correct memory + * size (return value of this function). + */ + if (n_ranks == 2) { + n_ranks = 1; + rank_density /= 2; + } else { + rank_density /= 2; + } } +#endif /* CONFIG_MPC8641HPCN */ + +#else /* CONFIG_DDR_INTERLEAVE */ + + if (dimm_num == 1) { + /* + * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg + */ + ddr->cs0_bnds = (start_addr >> 8) + | (((start_addr + rank_density - 1) >> 24)); + + ddr->cs0_config = ( 1 << 31 + | (odt_rd_cfg << 20) + | (odt_wr_cfg << 16) + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + + debug("DDR: cs0_bnds = 0x%08x\n", ddr->cs0_bnds); + debug("DDR: cs0_config = 0x%08x\n", ddr->cs0_config); + + if (n_ranks == 2) { + /* + * Eg: Bounds: 0x1000_0000 to 0x1f00_0000, + * second 256 Meg + */ + ddr->cs1_bnds = (((start_addr + rank_density) >> 8) + | (( start_addr + 2*rank_density - 1) + >> 24)); + ddr->cs1_config = ( 1<<31 + | (odt_rd_cfg << 20) + | (odt_wr_cfg << 16) + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + debug("DDR: cs1_bnds = 0x%08x\n", ddr->cs1_bnds); + debug("DDR: cs1_config = 0x%08x\n", ddr->cs1_config); + } + + } else { + /* + * This is the 2nd DIMM slot for this controller + */ + /* + * Eg: Bounds: 0x0000_0000 to 0x0f000_0000 first 256 Meg + */ + ddr->cs2_bnds = (start_addr >> 8) + | (((start_addr + rank_density - 1) >> 24)); + ddr->cs2_config = ( 1 << 31 + | (odt_rd_cfg << 20) + | (odt_wr_cfg << 16) + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + + debug("DDR: cs2_bnds = 0x%08x\n", ddr->cs2_bnds); + debug("DDR: cs2_config = 0x%08x\n", ddr->cs2_config); + + if (n_ranks == 2) { + /* + * Eg: Bounds: 0x1000_0000 to 0x1f00_0000, + * second 256 Meg + */ + ddr->cs3_bnds = (((start_addr + rank_density) >> 8) + | (( start_addr + 2*rank_density - 1) + >> 24)); + ddr->cs3_config = ( 1<<31 + | (odt_rd_cfg << 20) + | (odt_wr_cfg << 16) + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + debug("DDR: cs3_bnds = 0x%08x\n", ddr->cs3_bnds); + debug("DDR: cs3_config = 0x%08x\n", ddr->cs3_config); + } + } +#endif /* CONFIG_DDR_INTERLEAVE */ /* * Find the largest CAS by locating the highest 1 bit @@ -447,15 +569,14 @@ spd_sdram(void) unsigned char act_pd_exit = 2; /* Empirical? */ unsigned char pre_pd_exit = 6; /* Empirical? */ - ddr1->timing_cfg_0 = (0 + ddr->timing_cfg_0 = (0 | ((act_pd_exit & 0x7) << 20) /* ACT_PD_EXIT */ | ((pre_pd_exit & 0x7) << 16) /* PRE_PD_EXIT */ | ((taxpd_clk & 0xf) << 8) /* ODT_PD_EXIT */ | ((tmrd_clk & 0xf) << 0) /* MRS_CYC */ ); - debug("DDR: timing_cfg_0 = 0x%08x\n", ddr1->timing_cfg_0); + debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); - } else { } @@ -520,10 +641,10 @@ spd_sdram(void) /* * Sneak in some Extended Refresh Recovery. */ - ddr1->ext_refrec = (trfc_high << 16); - debug("DDR: ext_refrec = 0x%08x\n", ddr1->ext_refrec); + ddr->ext_refrec = (trfc_high << 16); + debug("DDR: ext_refrec = 0x%08x\n", ddr->ext_refrec); - ddr1->timing_cfg_1 = + ddr->timing_cfg_1 = (0 | ((picos_to_clk(spd.trp * 250) & 0x07) << 28) /* PRETOACT */ | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24) /* ACTTOPRE */ @@ -535,7 +656,7 @@ spd_sdram(void) | ((twtr_clk & 0x07) << 0) /* WRTORD */ ); - debug("DDR: timing_cfg_1 = 0x%08x\n", ddr1->timing_cfg_1); + debug("DDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); /* @@ -612,7 +733,7 @@ spd_sdram(void) } } - ddr1->timing_cfg_2 = (0 + ddr->timing_cfg_2 = (0 | ((add_lat & 0x7) << 28) /* ADD_LAT */ | ((cpo & 0x1f) << 23) /* CPO */ | ((wr_lat & 0x7) << 19) /* WR_LAT */ @@ -622,7 +743,7 @@ spd_sdram(void) | ((four_act & 0x1f) << 0) /* FOUR_ACT */ ); - debug("DDR: timing_cfg_2 = 0x%08x\n", ddr1->timing_cfg_2); + debug("DDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); /* @@ -673,7 +794,7 @@ spd_sdram(void) } /* - * Encoded Burst Lenght of 4. + * Encoded Burst Length of 4. */ burst_len = 2; /* Fiat. */ @@ -706,7 +827,7 @@ spd_sdram(void) mode_odt_enable = 0x40; /* 150 Ohm */ } - ddr1->sdram_mode_1 = + ddr->sdram_mode_1 = (0 | (add_lat << (16 + 3)) /* Additive Latency in EMRS1 */ | (mode_odt_enable << 16) /* ODT Enable in EMRS1 */ @@ -715,14 +836,14 @@ spd_sdram(void) | (burst_len << 0) /* Burst length */ ); - debug("DDR: sdram_mode = 0x%08x\n", ddr1->sdram_mode_1); + debug("DDR: sdram_mode = 0x%08x\n", ddr->sdram_mode_1); /* * Clear EMRS2 and EMRS3. */ - ddr1->sdram_mode_2 = 0; - debug("DDR: sdram_mode_2 = 0x%08x\n", ddr1->sdram_mode_2); + ddr->sdram_mode_2 = 0; + debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2); /* @@ -749,12 +870,12 @@ spd_sdram(void) * Set BSTOPRE to 0x100 for page mode * If auto-charge is used, set BSTOPRE = 0 */ - ddr1->sdram_interval = + ddr->sdram_interval = (0 | (refresh_clk & 0x3fff) << 16 | 0x100 ); - debug("DDR: sdram_interval = 0x%08x\n", ddr1->sdram_interval); + debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval); } /* @@ -763,11 +884,11 @@ spd_sdram(void) */ #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) if (spd.config == 0x02) { - ddr1->err_disable = 0x0000000d; - ddr1->err_sbe = 0x00ff0000; + ddr->err_disable = 0x0000000d; + ddr->err_sbe = 0x00ff0000; } - debug("DDR: err_disable = 0x%08x\n", ddr1->err_disable); - debug("DDR: err_sbe = 0x%08x\n", ddr1->err_sbe); + debug("DDR: err_disable = 0x%08x\n", ddr->err_disable); + debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe); #endif asm("sync;isync"); @@ -800,8 +921,8 @@ spd_sdram(void) * Use the DDR controller to auto initialize memory. */ d_init = 1; - ddr1->sdram_data_init = CONFIG_MEM_INIT_VALUE; - debug("DDR: ddr_data_init = 0x%08x\n", ddr1->sdram_data_init); + ddr->sdram_data_init = CONFIG_MEM_INIT_VALUE; + debug("DDR: ddr_data_init = 0x%08x\n", ddr->sdram_data_init); #else /* * Memory will be initialized via DMA, or not at all. @@ -809,13 +930,13 @@ spd_sdram(void) d_init = 0; #endif - ddr1->sdram_cfg_2 = (0 + ddr->sdram_cfg_2 = (0 | (dqs_cfg << 26) /* Differential DQS */ | (odt_cfg << 21) /* ODT */ | (d_init << 4) /* D_INIT auto init DDR */ ); - debug("DDR: sdram_cfg_2 = 0x%08x\n", ddr1->sdram_cfg_2); + debug("DDR: sdram_cfg_2 = 0x%08x\n", ddr->sdram_cfg_2); #ifdef MPC86xx_DDR_SDRAM_CLK_CNTL @@ -835,121 +956,373 @@ spd_sdram(void) clk_adjust = 0x7; } - ddr1->sdram_clk_cntl = (0 + ddr->sdram_clk_cntl = (0 | 0x80000000 | (clk_adjust << 23) ); - debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr1->sdram_clk_cntl); + debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl); } #endif + /* - * Figure out the settings for the sdram_cfg register. - * Build up the entire register in 'sdram_cfg' before writing - * since the write into the register will actually enable the - * memory controller; all settings must be done before enabling. - * - * sdram_cfg[0] = 1 (ddr sdram logic enable) - * sdram_cfg[1] = 1 (self-refresh-enable) - * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM) - * 010 DDR 1 SDRAM - * 011 DDR 2 SDRAM + * Figure out memory size in Megabytes. */ - sdram_type = (spd.mem_type == SPD_MEMTYPE_DDR) ? 2 : 3; - sdram_cfg_1 = (0 - | (1 << 31) /* Enable */ - | (1 << 30) /* Self refresh */ - | (sdram_type << 24) /* SDRAM type */ - ); + debug("# ranks = %d, rank_density = 0x%08lx\n", n_ranks, rank_density); + memsize = n_ranks * rank_density / 0x100000; + return memsize; +} + + +unsigned int enable_ddr(unsigned int ddr_num) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + spd_eeprom_t spd1,spd2; + volatile ccsr_ddr_t *ddr; + unsigned sdram_cfg_1; + unsigned char sdram_type, mem_type, config, mod_attr; + unsigned char d_init; + unsigned int no_dimm1=0, no_dimm2=0; + + /* Set up pointer to enable the current ddr controller */ + if (ddr_num == 1) + ddr = &immap->im_ddr1; + else + ddr = &immap->im_ddr2; /* - * sdram_cfg[3] = RD_EN - registered DIMM enable - * A value of 0x26 indicates micron registered DIMMS (micron.com) + * Read both dimm slots and decide whether + * or not to enable this controller. */ - if (spd.mem_type == SPD_MEMTYPE_DDR && spd.mod_attr == 0x26) { - sdram_cfg_1 |= 0x10000000; /* RD_EN */ + memset((void *)&spd1,0,sizeof(spd1)); + memset((void *)&spd2,0,sizeof(spd2)); + + if (ddr_num == 1) { + CFG_READ_SPD(SPD_EEPROM_ADDRESS1, + 0, 1, (uchar *) &spd1, sizeof(spd1)); + CFG_READ_SPD(SPD_EEPROM_ADDRESS2, + 0, 1, (uchar *) &spd2, sizeof(spd2)); + } else { + CFG_READ_SPD(SPD_EEPROM_ADDRESS3, + 0, 1, (uchar *) &spd1, sizeof(spd1)); + CFG_READ_SPD(SPD_EEPROM_ADDRESS4, + 0, 1, (uchar *) &spd2, sizeof(spd2)); } -#if defined(CONFIG_DDR_ECC) /* - * If the user wanted ECC (enabled via sdram_cfg[2]) + * Check for supported memory module types. */ - if (spd.config == 0x02) { - sdram_cfg_1 |= 0x20000000; /* ECC_EN */ + if (spd1.mem_type != SPD_MEMTYPE_DDR + && spd1.mem_type != SPD_MEMTYPE_DDR2) { + no_dimm1 = 1; + } else { + debug("\nFound memory of type 0x%02lx ",spd1.mem_type ); + if (spd1.mem_type == SPD_MEMTYPE_DDR) + debug("DDR I\n"); + else + debug("DDR II\n"); + } + + if (spd2.mem_type != SPD_MEMTYPE_DDR && + spd2.mem_type != SPD_MEMTYPE_DDR2) { + no_dimm2 = 1; + } else { + debug("\nFound memory of type 0x%02lx ",spd2.mem_type ); + if (spd2.mem_type == SPD_MEMTYPE_DDR) + debug("DDR I\n"); + else + debug("DDR II\n"); + } + +#ifdef CONFIG_DDR_INTERLEAVE + if (no_dimm1) { + printf("For interleaved operation memory modules need to be present in CS0 DIMM slots of both DDR controllers!\n"); + return 0; } #endif /* - * REV1 uses 1T timing. - * REV2 may use 1T or 2T as configured by the user. + * Memory is not present in DIMM1 and DIMM2 - so do not enable DDRn */ - { - uint pvr = get_pvr(); + if (no_dimm1 && no_dimm2) { + printf("No memory modules found for DDR controller %d!!\n", ddr_num); + return 0; + } else { + mem_type = no_dimm2 ? spd1.mem_type : spd2.mem_type; - if (pvr != PVR_85xx_REV1) { -#if defined(CONFIG_DDR_2T_TIMING) - /* - * Enable 2T timing by setting sdram_cfg[16]. - */ - sdram_cfg_1 |= 0x8000; /* 2T_EN */ + /* + * Figure out the settings for the sdram_cfg register. + * Build up the entire register in 'sdram_cfg' before + * writing since the write into the register will + * actually enable the memory controller; all settings + * must be done before enabling. + * + * sdram_cfg[0] = 1 (ddr sdram logic enable) + * sdram_cfg[1] = 1 (self-refresh-enable) + * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM) + * 010 DDR 1 SDRAM + * 011 DDR 2 SDRAM + */ + sdram_type = (mem_type == SPD_MEMTYPE_DDR) ? 2 : 3; + sdram_cfg_1 = (0 + | (1 << 31) /* Enable */ + | (1 << 30) /* Self refresh */ + | (sdram_type << 24) /* SDRAM type */ + ); + + /* + * sdram_cfg[3] = RD_EN - registered DIMM enable + * A value of 0x26 indicates micron registered + * DIMMS (micron.com) + */ + mod_attr = no_dimm2 ? spd1.mod_attr : spd2.mod_attr; + if (mem_type == SPD_MEMTYPE_DDR && mod_attr == 0x26) { + sdram_cfg_1 |= 0x10000000; /* RD_EN */ + } + +#if defined(CONFIG_DDR_ECC) + + config = no_dimm2 ? spd1.config : spd2.config; + + /* + * If the user wanted ECC (enabled via sdram_cfg[2]) + */ + if (config == 0x02) { + ddr->err_disable = 0x00000000; + asm("sync;isync;"); + ddr->err_sbe = 0x00ff0000; + ddr->err_int_en = 0x0000000d; + sdram_cfg_1 |= 0x20000000; /* ECC_EN */ + } #endif + + /* + * Set 1T or 2T timing based on 1 or 2 modules + */ + { + if (!(no_dimm1 || no_dimm2)) { + /* + * 2T timing,because both DIMMS are present. + * Enable 2T timing by setting sdram_cfg[16]. + */ + sdram_cfg_1 |= 0x8000; /* 2T_EN */ + } } - } - /* - * 200 painful micro-seconds must elapse between - * the DDR clock setup and the DDR config enable. - */ - udelay(200); + /* + * 200 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + */ + udelay(200); - /* - * Go! - */ - ddr1->sdram_cfg_1 = sdram_cfg_1; + /* + * Go! + */ + ddr->sdram_cfg_1 = sdram_cfg_1; - asm("sync;isync"); - udelay(500); + asm volatile("sync;isync"); + udelay(500); - debug("DDR: sdram_cfg = 0x%08x\n", ddr1->sdram_cfg_1); + debug("DDR: sdram_cfg = 0x%08x\n", ddr->sdram_cfg_1); #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) - debug("DDR: memory initializing\n"); - /* - * Poll until memory is initialized. - * 512 Meg at 400 might hit this 200 times or so. - */ - while ((ddr1->sdram_cfg_2 & (d_init << 4)) != 0) { - udelay(1000); + d_init = 1; + debug("DDR: memory initializing\n"); + + /* + * Poll until memory is initialized. + * 512 Meg at 400 might hit this 200 times or so. + */ + while ((ddr->sdram_cfg_2 & (d_init << 4)) != 0) { + udelay(1000); + } + debug("DDR: memory initialized\n\n"); +#endif + + debug("Enabled DDR Controller %d\n", ddr_num); + return 1; } - debug("DDR: memory initialized\n"); +} + + +long int +spd_sdram(void) +{ + int memsize_ddr1_dimm1 = 0; + int memsize_ddr1_dimm2 = 0; + int memsize_ddr2_dimm1 = 0; + int memsize_ddr2_dimm2 = 0; + int memsize_total = 0; + int memsize_ddr1 = 0; + int memsize_ddr2 = 0; + unsigned int ddr1_enabled = 0; + unsigned int ddr2_enabled = 0; + unsigned int law_size_ddr1; + unsigned int law_size_ddr2; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile ccsr_ddr_t *ddr1 = &immap->im_ddr1; + volatile ccsr_ddr_t *ddr2 = &immap->im_ddr2; + volatile ccsr_local_mcm_t *mcm = &immap->im_local_mcm; + +#ifdef CONFIG_DDR_INTERLEAVE + unsigned int law_size_interleaved; + + memsize_ddr1_dimm1 = spd_init(SPD_EEPROM_ADDRESS1, + 1, 1, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr1_dimm1; + + memsize_ddr2_dimm1 = spd_init(SPD_EEPROM_ADDRESS3, + 2, 1, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr2_dimm1; + + if (memsize_ddr1_dimm1 != memsize_ddr2_dimm1) { + if (memsize_ddr1_dimm1 < memsize_ddr2_dimm1) + memsize_total -= memsize_ddr1_dimm1; + else + memsize_total -= memsize_ddr2_dimm1; + debug("Total memory available for interleaving 0x%08lx\n", + memsize_total * 1024 * 1024); + debug("Adjusting CS0_BNDS to account for unequal DIMM sizes in interleaved memory\n"); + ddr1->cs0_bnds = ((memsize_total * 1024 * 1024) - 1) >> 24; + ddr2->cs0_bnds = ((memsize_total * 1024 * 1024) - 1) >> 24; + debug("DDR1: cs0_bnds = 0x%08x\n", ddr1->cs0_bnds); + debug("DDR2: cs0_bnds = 0x%08x\n", ddr2->cs0_bnds); + } + + ddr1_enabled = enable_ddr(1); + ddr2_enabled = enable_ddr(2); + + /* + * Both controllers need to be enabled for interleaving. + */ + if (ddr1_enabled && ddr2_enabled) { + law_size_interleaved = 19 + __ilog2(memsize_total); + + /* + * Set up LAWBAR for DDR 1 space. + */ + mcm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); + mcm->lawar1 = (LAWAR_EN + | LAWAR_TRGT_IF_DDR_INTERLEAVED + | (LAWAR_SIZE & law_size_interleaved)); + debug("DDR: LAWBAR1=0x%08x\n", mcm->lawbar1); + debug("DDR: LAWAR1=0x%08x\n", mcm->lawar1); + debug("Interleaved memory size is 0x%08lx\n", memsize_total); + +#ifdef CONFIG_DDR_INTERLEAVE +#if (CFG_PAGE_INTERLEAVING == 1) + printf("Page "); +#elif (CFG_BANK_INTERLEAVING == 1) + printf("Bank "); +#elif (CFG_SUPER_BANK_INTERLEAVING == 1) + printf("Super-bank "); +#else + printf("Cache-line "); #endif +#endif + printf("Interleaved"); + return memsize_total * 1024 * 1024; + } else { + printf("Interleaved memory not enabled - check CS0 DIMM slots for both controllers.\n"); + return 0; + } + +#else + /* + * Call spd_sdram() routine to init ddr1 - pass I2c address, + * controller number, dimm number, and starting address. + */ + memsize_ddr1_dimm1 = spd_init(SPD_EEPROM_ADDRESS1, + 1, 1, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr1_dimm1; + memsize_ddr1_dimm2 = spd_init(SPD_EEPROM_ADDRESS2, + 1, 2, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr1_dimm2; /* - * Figure out memory size in Megabytes. + * Enable the DDR controller - pass ddr controller number. */ - memsize = n_ranks * rank_density / 0x100000; + ddr1_enabled = enable_ddr(1); + /* Keep track of memory to be addressed by DDR1 */ + memsize_ddr1 = memsize_ddr1_dimm1 + memsize_ddr1_dimm2; - /* + /* * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23. Fnord. */ - law_size = 19 + __ilog2(memsize); + if (ddr1_enabled) { + law_size_ddr1 = 19 + __ilog2(memsize_ddr1); + + /* + * Set up LAWBAR for DDR 1 space. + */ + mcm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); + mcm->lawar1 = (LAWAR_EN + | LAWAR_TRGT_IF_DDR1 + | (LAWAR_SIZE & law_size_ddr1)); + debug("DDR: LAWBAR1=0x%08x\n", mcm->lawbar1); + debug("DDR: LAWAR1=0x%08x\n", mcm->lawar1); + } + +#if (CONFIG_NUM_DDR_CONTROLLERS > 1) + memsize_ddr2_dimm1 = spd_init(SPD_EEPROM_ADDRESS3, + 2, 1, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr2_dimm1; + + memsize_ddr2_dimm2 = spd_init(SPD_EEPROM_ADDRESS4, + 2, 2, + (unsigned int)memsize_total * 1024*1024); + memsize_total += memsize_ddr2_dimm2; + + ddr2_enabled = enable_ddr(2); + + /* Keep track of memory to be addressed by DDR2 */ + memsize_ddr2 = memsize_ddr2_dimm1 + memsize_ddr2_dimm2; + + if (ddr2_enabled) { + law_size_ddr2 = 19 + __ilog2(memsize_ddr2); + + /* + * Set up LAWBAR for DDR 2 space. + */ + if (ddr1_enabled) + mcm->lawbar8 = (((memsize_ddr1 * 1024 * 1024) >> 12) + & 0xfffff); + else + mcm->lawbar8 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); + + mcm->lawar8 = (LAWAR_EN + | LAWAR_TRGT_IF_DDR2 + | (LAWAR_SIZE & law_size_ddr2)); + debug("\nDDR: LAWBAR8=0x%08x\n", mcm->lawbar8); + debug("DDR: LAWAR8=0x%08x\n", mcm->lawar8); + } +#endif /* CONFIG_NUM_DDR_CONTROLLERS > 1 */ + + debug("\nMemory sizes are DDR1 = 0x%08lx, DDR2 = 0x%08lx\n", + memsize_ddr1, memsize_ddr2); /* - * Set up LAWBAR for all of DDR. + * If neither DDR controller is enabled return 0. */ - mcm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff); - mcm->lawar1 = (LAWAR_EN - | LAWAR_TRGT_IF_DDR - | (LAWAR_SIZE & law_size)); - debug("DDR: LAWBAR1=0x%08x\n", mcm->lawbar1); - debug("DDR: LARAR1=0x%08x\n", mcm->lawar1); + if (!ddr1_enabled && !ddr2_enabled) + return 0; + else { + printf("Non-interleaved"); + return memsize_total * 1024 * 1024; + } - return memsize * 1024 * 1024; +#endif /* CONFIG_DDR_INTERLEAVE */ } + #endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/mpc86xx/speed.c b/cpu/mpc86xx/speed.c index a08ae5f..5e05ab8 100644 --- a/cpu/mpc86xx/speed.c +++ b/cpu/mpc86xx/speed.c @@ -1,6 +1,6 @@ /* * Copyright 2004 Freescale Semiconductor. - * Jeff Brown (jeffrey@freescale.com) + * Jeff Brown * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) * * (C) Copyright 2000-2002 @@ -29,9 +29,6 @@ #include <mpc86xx.h> #include <asm/processor.h> -unsigned long get_board_sys_clk(ulong dummy); -unsigned long get_sysclk_from_px_regs(void); - void get_sys_info (sys_info_t *sysInfo) { @@ -39,11 +36,11 @@ void get_sys_info (sys_info_t *sysInfo) volatile ccsr_gur_t *gur = &immap->im_gur; uint plat_ratio, e600_ratio; - plat_ratio = (gur->porpllsr) & 0x0000003e; + plat_ratio = (gur->porpllsr) & 0x0000003e; plat_ratio >>= 1; switch(plat_ratio) { - case 0x0: + case 0x0: sysInfo->freqSystemBus = 16 * CONFIG_SYS_CLK_FREQ; break; case 0x02: @@ -55,19 +52,14 @@ void get_sys_info (sys_info_t *sysInfo) case 0x09: case 0x0a: case 0x0c: - case 0x10: - sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ; - break; + case 0x10: + sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ; + break; default: sysInfo->freqSystemBus = 0; break; } -#if 0 - printf("assigned system bus freq = %d for plat ratio 0x%08lx\n", - sysInfo->freqSystemBus, plat_ratio); -#endif - e600_ratio = (gur->porpllsr) & 0x003f0000; e600_ratio >>= 16; @@ -75,13 +67,13 @@ void get_sys_info (sys_info_t *sysInfo) case 0x10: sysInfo->freqProcessor = 2 * sysInfo->freqSystemBus; break; - case 0x19: + case 0x19: sysInfo->freqProcessor = 5 * sysInfo->freqSystemBus/2; break; case 0x20: sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus; break; - case 0x39: + case 0x39: sysInfo->freqProcessor = 7 * sysInfo->freqSystemBus/2; break; case 0x28: @@ -90,16 +82,10 @@ void get_sys_info (sys_info_t *sysInfo) case 0x1d: sysInfo->freqProcessor = 9 * sysInfo->freqSystemBus/2; break; - default: - /* JB - Emulator workaround until real cop is plugged in */ - /* sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus; */ + default: sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus; break; } -#if 0 - printf("assigned processor freq = %d for e600 ratio 0x%08lx\n", - sysInfo->freqProcessor, e600_ratio); -#endif } @@ -128,6 +114,7 @@ int get_clocks(void) * get_bus_freq * Return system bus freq in Hz */ + ulong get_bus_freq(ulong dummy) { ulong val; @@ -139,42 +126,6 @@ ulong get_bus_freq(ulong dummy) return val; } -unsigned long get_sysclk_from_px_regs() -{ - ulong val; - u8 vclkh, vclkl; - - vclkh = in8(PIXIS_BASE + PIXIS_VCLKH); - vclkl = in8(PIXIS_BASE + PIXIS_VCLKL); - - if ((vclkh == 0x84) && (vclkl == 0x07)) { - val = 33000000; - } - if ((vclkh == 0x3F) && (vclkl == 0x20)) { - val = 40000000; - } - if ((vclkh == 0x3F) && (vclkl == 0x2A)) { - val = 50000000; - } - if ((vclkh == 0x24) && (vclkl == 0x04)) { - val = 66000000; - } - if ((vclkh == 0x3F) && (vclkl == 0x4B)) { - val = 83000000; - } - if ((vclkh == 0x3F) && (vclkl == 0x5C)) { - val = 100000000; - } - if ((vclkh == 0xDF) && (vclkl == 0x3B)) { - val = 134000000; - } - if ((vclkh == 0xDF) && (vclkl == 0x4B)) { - val = 166000000; - } - - return val; -} - /* * get_board_sys_clk diff --git a/cpu/mpc86xx/start.S b/cpu/mpc86xx/start.S index b963631..07e7557 100644 --- a/cpu/mpc86xx/start.S +++ b/cpu/mpc86xx/start.S @@ -207,11 +207,7 @@ boot_warm: /* init the L2 cache */ addis r3, r0, L2_INIT@h ori r3, r3, L2_INIT@l - sync mtspr l2cr, r3 -#ifdef CONFIG_ALTIVEC - dssall -#endif /* invalidate the L2 cache */ bl l2cache_invalidate sync @@ -245,6 +241,13 @@ in_flash: bl setup_ccsrbar #endif + /* Fix for SMP linux - Changing arbitration to round-robin */ + lis r3, CFG_CCSRBAR@h + ori r3, r3, 0x1000 + xor r4, r4, r4 + li r4, 0x1000 + stw r4, 0(r3) + /* setup the law entries */ bl law_entry sync @@ -280,9 +283,9 @@ in_flash: /* make sure timer enabled in guts register too */ lis r3, CFG_CCSRBAR@h oris r3,r3, 0xE - ori r3,r3,0x0070 /*Jason from 3*/ + ori r3,r3,0x0070 lwz r4, 0(r3) - lis r5,0xFFFC /*Jason from 0xffff*/ + lis r5,0xFFFC ori r5,r5,0x5FFF and r4,r4,r5 stw r4,0(r3) |