diff options
author | Dave Liu <daveliu@freescale.com> | 2006-11-03 19:33:44 -0600 |
---|---|---|
committer | Kim Phillips <kim.phillips@freescale.com> | 2006-11-03 19:42:21 -0600 |
commit | 5f8204394e39bbe8cd9f08b8f8d145b6c01f7c73 (patch) | |
tree | 942e90db9c4f442108025ae360fa54b9a74277ea /cpu/mpc83xx/spd_sdram.c | |
parent | 23892e49352de74f7fac36ff90bb1be143d195e3 (diff) |
mpc83xx: Add MPC8360EMDS basic board support
Add support for the Freescale MPC8360EMDS board.
Includes DDR, DUART, Local Bus, PCI.
Diffstat (limited to 'cpu/mpc83xx/spd_sdram.c')
-rw-r--r-- | cpu/mpc83xx/spd_sdram.c | 304 |
1 files changed, 151 insertions, 153 deletions
diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 3dfde8ac047..acc8c9e79b6 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -4,7 +4,7 @@ * (C) Copyright 2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * Copyright 2004 Freescale Semiconductor. + * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. * (C) Copyright 2003 Motorola Inc. * Xianghua Xiao (X.Xiao@motorola.com) * @@ -112,14 +112,10 @@ static void spd_debug(spd_eeprom_t *spd) long int spd_sdram() { -#ifdef CONFIG_MPC834X - int caslat_83xx; /* For Errata DDR6 */ -#endif volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; volatile ddr83xx_t *ddr = &immap->ddr; volatile law83xx_t *ecm = &immap->sysconf.ddrlaw[0]; spd_eeprom_t spd; - unsigned int tmp, tmp1; unsigned int memsize; unsigned int law_size; unsigned char caslat, caslat_ctrl; @@ -131,28 +127,7 @@ long int spd_sdram() unsigned sdram_cfg; unsigned int ddrc_ecc_enable; - /* Read SPD parameters with I2C */ -#ifdef CFG_83XX_DDR_USES_CS0 - ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1; - ddr->cs_config[0] = ( 1 << 31 - | (spd.nrow_addr - 12) << 8 - | (spd.ncol_addr - 8) ); - debug("\n"); - debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds); - debug("cs0_config = 0x%08x\n",ddr->cs_config[0]); - - if (spd.nrows == 2) { - ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8) - | ((banksize(spd.row_dens) >> 23) - 1) ); - ddr->cs_config[1] = ( 1<<31 - | (spd.nrow_addr-12) << 8 - | (spd.ncol_addr-8) ); - debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds); - debug("cs1_config = 0x%08x\n",ddr->cs_config[1]); - } - -#else CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); #ifdef SPD_DEBUG spd_debug(&spd); @@ -183,6 +158,26 @@ long int spd_sdram() return 0; } /* Setup DDR chip select register */ +#ifdef CFG_83XX_DDR_USES_CS0 + ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1; + ddr->cs_config[0] = ( 1 << 31 + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + debug("\n"); + debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds); + debug("cs0_config = 0x%08x\n",ddr->cs_config[0]); + + if (spd.nrows == 2) { + ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8) + | ((banksize(spd.row_dens) >> 23) - 1) ); + ddr->cs_config[1] = ( 1<<31 + | (spd.nrow_addr-12) << 8 + | (spd.ncol_addr-8) ); + debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds); + debug("cs1_config = 0x%08x\n",ddr->cs_config[1]); + } + +#else ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1; ddr->cs_config[2] = ( 1 << 31 | (spd.nrow_addr - 12) << 8 @@ -243,8 +238,9 @@ long int spd_sdram() */ caslat = __ilog2(spd.cas_lat); - if (caslat > 4 ) { - printf("DDR: Invalid SPD CAS Latency, caslat=%02X\n", caslat); + if (caslat > 6 ) { + printf("DDR: Invalid SPD CAS Latency, caslat=%02X\n", + spd.cas_lat); return 0; } max_bus_clk = 1000 *10 / (((spd.clk_cycle & 0xF0) >> 4) * 10 @@ -256,89 +252,110 @@ long int spd_sdram() ddrc_clk = get_ddr_clk(0) / 1000000; if (max_data_rate >= 390) { /* it is DDR 400 */ - printf("DDR: platform not support DDR 400\n"); - return 0; + if (ddrc_clk <= 410 && ddrc_clk > 350) { + /* DDR controller clk at 350~410 */ + effective_data_rate = 400; /* 5ns */ + caslat = caslat; + } else if (ddrc_clk <= 350 && ddrc_clk > 280) { + /* DDR controller clk at 280~350 */ + effective_data_rate = 333; /* 6ns */ + if (spd.clk_cycle2 == 0x60) { + caslat = caslat - 1; + } else { + caslat = caslat; + } + } else if (ddrc_clk <= 280 && ddrc_clk > 230) { + /* DDR controller clk at 230~280 */ + effective_data_rate = 266; /* 7.5ns */ + if (spd.clk_cycle3 == 0x75) { + caslat = caslat - 2; + } else if (spd.clk_cycle2 == 0x60) { + caslat = caslat - 1; + } else { + caslat = caslat; + } + } else if (ddrc_clk <= 230 && ddrc_clk > 90) { + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ + if (spd.clk_cycle3 == 0x75) { + caslat = caslat - 2; + } else if (spd.clk_cycle2 == 0x60) { + caslat = caslat - 1; + } else { + caslat = caslat; + } + } } else if (max_data_rate >= 323) { /* it is DDR 333 */ if (ddrc_clk <= 350 && ddrc_clk > 280) { - /* DDRC clk at 280~350 */ + /* DDR controller clk at 280~350 */ effective_data_rate = 333; /* 6ns */ caslat = caslat; } else if (ddrc_clk <= 280 && ddrc_clk > 230) { - /* DDRC clk at 230~280 */ + /* DDR controller clk at 230~280 */ + effective_data_rate = 266; /* 7.5ns */ if (spd.clk_cycle2 == 0x75) { - effective_data_rate = 266; /* 7.5ns */ caslat = caslat - 1; + } else { + caslat = caslat; } } else if (ddrc_clk <= 230 && ddrc_clk > 90) { - /* DDRC clk at 90~230 */ + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ if (spd.clk_cycle3 == 0xa0) { - effective_data_rate = 200; /* 10ns */ caslat = caslat - 2; + } else if (spd.clk_cycle2 == 0x75) { + caslat = caslat - 1; + } else { + caslat = caslat; } } } else if (max_data_rate >= 256) { /* it is DDR 266 */ if (ddrc_clk <= 350 && ddrc_clk > 280) { - /* DDRC clk at 280~350 */ + /* DDR controller clk at 280~350 */ printf("DDR: DDR controller freq is more than " "max data rate of the module\n"); return 0; } else if (ddrc_clk <= 280 && ddrc_clk > 230) { - /* DDRC clk at 230~280 */ + /* DDR controller clk at 230~280 */ effective_data_rate = 266; /* 7.5ns */ caslat = caslat; } else if (ddrc_clk <= 230 && ddrc_clk > 90) { - /* DDRC clk at 90~230 */ + /* DDR controller clk at 90~230 */ + effective_data_rate = 200; /* 10ns */ if (spd.clk_cycle2 == 0xa0) { - effective_data_rate = 200; /* 10ns */ caslat = caslat - 1; } } } else if (max_data_rate >= 190) { /* it is DDR 200 */ if (ddrc_clk <= 350 && ddrc_clk > 230) { - /* DDRC clk at 230~350 */ + /* DDR controller clk at 230~350 */ printf("DDR: DDR controller freq is more than " "max data rate of the module\n"); return 0; } else if (ddrc_clk <= 230 && ddrc_clk > 90) { - /* DDRC clk at 90~230 */ + /* DDR controller clk at 90~230 */ effective_data_rate = 200; /* 10ns */ caslat = caslat; } } -#ifdef CONFIG_MPC834X -/* Errata DDR6 - This errata affects all MPC8349E, MPC8343E and MPC8347E processors. -*/ - if ((tmp1 >= 280) && (tmp1 < 350)) /* CSB=333 */ - { - if (spd.mid[0] == 0x2c) { - /* Micron memory running at 333 MHz */ - /* Chances are, U-Boot will crash before we get here, - but just in case, display a message and return error. */ - printf("Micron DDR not supported at 333MHz CSB\n"); - return 0; - } else if (spd.mid[0] == 0xad) { - printf("Hynix DDR does not require Errata DDR6\n"); - } else { - /* enable 2 cycle Earlier for CL=2.5 or 3 */ - ddr->debug_reg = 0x202c0000; - printf("Errata DDR6 (debug_reg=0x%x)\n", ddr->debug_reg); - } - caslat_83xx = caslat; - } - - if ((tmp1 >= 230) && (tmp1 < 280)) { /* CSB=266 */ - if (spd.mid[0] != 0x2c) /* non-Micron */ - caslat_83xx = caslat - 1; + debug("DDR:Effective data rate is: %dMhz\n", effective_data_rate); + debug("DDR:The MSB 1 of CAS Latency is: %d\n", caslat); + /* + * Errata DDR6 work around: input enable 2 cycles earlier. + * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2. + */ + if (caslat == 2) { + ddr->debug_reg = 0x201c0000; /* CL=2 */ + } else if (caslat == 3) { + ddr->debug_reg = 0x202c0000; /* CL=2.5 */ + } else if (caslat == 4) { + ddr->debug_reg = 0x202c0000; /* CL=3.0 */ } + __asm__ __volatile__ ("sync"); - if ((tmp1 >= 90) && (tmp1 < 230)) { /* CSB=200 */ - caslat = 3; - caslat_83xx = 2; - } -#endif + debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg); /* * note: caslat must also be programmed into ddr->sdram_mode @@ -353,11 +370,7 @@ long int spd_sdram() (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) | ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) | -#ifdef CONFIG_MPC834x - ((caslat_83xx & 0x07) << 16 ) | -#else ((caslat_ctrl & 0x07) << 16 ) | -#endif (((picos_to_clk(spd.trfc * 1000) - 8) & 0x0f) << 12 ) | ( 0x300 ) | ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1); @@ -370,13 +383,10 @@ long int spd_sdram() ddr->sdram_cfg = 0x42000000; /* Check DIMM data bus width */ - if (spd.dataw_lsb == 0x20) - { + if (spd.dataw_lsb == 0x20) { burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ printf("\n DDR DIMM: data bus width is 32 bit"); - } - else - { + } else { burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */ printf("\n DDR DIMM: data bus width is 64 bit"); } @@ -384,68 +394,67 @@ long int spd_sdram() /* Is this an ECC DDR chip? */ if (spd.config == 0x02) { printf(" with ECC\n"); - } - else + } else { printf(" without ECC\n"); + } /* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus, Burst type is sequential */ - switch(caslat) { - case 1: - ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */ - break; - case 2: - ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */ - break; - case 3: - ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */ - break; - case 4: - ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */ - break; - default: - printf("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 " - "is supported.\n"); - return 0; + switch (caslat) { + case 1: + ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */ + break; + case 2: + ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */ + break; + case 3: + ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */ + break; + case 4: + ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */ + break; + default: + printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n"); + return 0; } debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode); - switch(spd.refresh) { - case 0x00: - case 0x80: - tmp = picos_to_clk(15625000); - break; - case 0x01: - case 0x81: - tmp = picos_to_clk(3900000); - break; - case 0x02: - case 0x82: - tmp = picos_to_clk(7800000); - break; - case 0x03: - case 0x83: - tmp = picos_to_clk(31300000); - break; - case 0x04: - case 0x84: - tmp = picos_to_clk(62500000); - break; - case 0x05: - case 0x85: - tmp = picos_to_clk(125000000); - break; - default: - tmp = 0x512; - break; + switch (spd.refresh) { + case 0x00: + case 0x80: + refresh_clk = picos_to_clk(15625000); + break; + case 0x01: + case 0x81: + refresh_clk = picos_to_clk(3900000); + break; + case 0x02: + case 0x82: + refresh_clk = picos_to_clk(7800000); + break; + case 0x03: + case 0x83: + refresh_clk = picos_to_clk(31300000); + break; + case 0x04: + case 0x84: + refresh_clk = picos_to_clk(62500000); + break; + case 0x05: + case 0x85: + refresh_clk = picos_to_clk(125000000); + break; + default: + refresh_clk = 0x512; + break; } /* * Set BSTOPRE to 0x100 for page mode * If auto-charge is used, set BSTOPRE = 0 */ - ddr->sdram_interval = ((tmp & 0x3fff) << 16) | 0x100; + ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100; debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval); /* SS_EN = 0, source synchronous disable @@ -459,8 +468,8 @@ long int spd_sdram() udelay(600); /* - * Figure out the settings for the sdram_cfg register. Build up - * the entire register in 'tmp' before writing since the write into + * Figure out the settings for the sdram_cfg register. Build up + * the value in 'sdram_cfg' before writing since the write into * the register will actually enable the memory controller, and all * settings must be done before enabling. * @@ -493,13 +502,13 @@ long int spd_sdram() /* set single bit error threshold to maximum value, * reset counter to zero */ ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) | - (0 << ECC_ERROR_MAN_SBEC_SHIFT); + (0 << ECC_ERROR_MAN_SBEC_SHIFT); } debug("DDR:err_disable=0x%08x\n", ddr->err_disable); debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe); #endif - printf(" DDRC ECC mode: %s", ddrc_ecc_enable ? "ON":"OFF"); + printf(" DDRC ECC mode: %s\n", ddrc_ecc_enable ? "ON":"OFF"); #if defined(CONFIG_DDR_2T_TIMING) /* @@ -517,7 +526,6 @@ long int spd_sdram() } #endif /* CONFIG_SPD_EEPROM */ - #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC) /* * Use timebase counter, get_timer() is not availabe @@ -602,26 +610,16 @@ void ddr_enable_ecc(unsigned int dram_size) } } - /* 8K */ - dma_xfer((uint *)0x2000, 0x2000, (uint *)0); - /* 16K */ - dma_xfer((uint *)0x4000, 0x4000, (uint *)0); - /* 32K */ - dma_xfer((uint *)0x8000, 0x8000, (uint *)0); - /* 64K */ - dma_xfer((uint *)0x10000, 0x10000, (uint *)0); - /* 128k */ - dma_xfer((uint *)0x20000, 0x20000, (uint *)0); - /* 256k */ - dma_xfer((uint *)0x40000, 0x40000, (uint *)0); - /* 512k */ - dma_xfer((uint *)0x80000, 0x80000, (uint *)0); - /* 1M */ - dma_xfer((uint *)0x100000, 0x100000, (uint *)0); - /* 2M */ - dma_xfer((uint *)0x200000, 0x200000, (uint *)0); - /* 4M */ - dma_xfer((uint *)0x400000, 0x400000, (uint *)0); + dma_xfer((uint *)0x2000, 0x2000, (uint *)0); /* 8K */ + dma_xfer((uint *)0x4000, 0x4000, (uint *)0); /* 16K */ + dma_xfer((uint *)0x8000, 0x8000, (uint *)0); /* 32K */ + dma_xfer((uint *)0x10000, 0x10000, (uint *)0); /* 64K */ + dma_xfer((uint *)0x20000, 0x20000, (uint *)0); /* 128K */ + dma_xfer((uint *)0x40000, 0x40000, (uint *)0); /* 256K */ + dma_xfer((uint *)0x80000, 0x80000, (uint *)0); /* 512K */ + dma_xfer((uint *)0x100000, 0x100000, (uint *)0); /* 1M */ + dma_xfer((uint *)0x200000, 0x200000, (uint *)0); /* 2M */ + dma_xfer((uint *)0x400000, 0x400000, (uint *)0); /* 4M */ for (i = 1; i < dram_size / 0x800000; i++) { dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0); |