void do_program_ecc(unsigned long tlb_word2_i_value) { unsigned long mcopt1; unsigned long mcopt2; unsigned long mcstat; phys_size_t memsize = sdram_memsize(); if (memsize > CONFIG_MAX_MEM_MAPPED) { printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n"); return; } mfsdram(SDRAM_MCOPT1, mcopt1); mfsdram(SDRAM_MCOPT2, mcopt2); if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { /* DDR controller must be enabled and not in self-refresh. */ mfsdram(SDRAM_MCSTAT, mcstat); if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { program_ecc_addr(0, memsize, tlb_word2_i_value); } } }
void board_add_ram_info(int use_default) { PPC4xx_SYS_INFO board_cfg; u32 val; mfsdram(DDR0_22, val); val &= DDR0_22_CTRL_RAW_MASK; switch (val) { case DDR0_22_CTRL_RAW_ECC_DISABLE: puts(" (ECC disabled"); break; case DDR0_22_CTRL_RAW_ECC_CHECK_ONLY: puts(" (ECC check only"); break; case DDR0_22_CTRL_RAW_NO_ECC_RAM: puts(" (no ECC ram"); break; case DDR0_22_CTRL_RAW_ECC_ENABLE: puts(" (ECC enabled"); break; } get_sys_info(&board_cfg); printf(", %d MHz", (board_cfg.freqPLB * 2) / 1000000); mfsdram(DDR0_03, val); val = DDR0_03_CASLAT_DECODE(val); printf(", CL%d)", val); }
/*---------------------------------------------------------------------------+ * program_ecc. *---------------------------------------------------------------------------*/ static void program_ecc(unsigned long start_address, unsigned long num_bytes) { u32 val; char str[] = "ECC generation -"; #if defined(CONFIG_PRAM) u32 *magicPtr; u32 magic; if ((mfspr(dbcr0) & 0x80000000) == 0) { /* only if no external debugger is alive! * Check whether vxWorks is using EDR logging, if yes zero * also PostMortem and user reserved memory */ magicPtr = (u32 *)(start_address + num_bytes - (CONFIG_PRAM*1024) + sizeof(u32)); magic = in_be32(magicPtr); debug("%s: CONFIG_PRAM %d kB magic 0x%x 0x%p\n", __FUNCTION__, CONFIG_PRAM, magicPtr, magic); if (magic == 0xbeefbabe) { printf("%s: preserving at %p\n", __FUNCTION__, magicPtr); num_bytes -= (CONFIG_PRAM*1024) - PM_RESERVED_MEM; } } #endif sync(); eieio(); puts(str); /* ECC bit set method for cached memory */ /* Fast method, no noticeable delay */ dcbz_area(start_address, num_bytes); dflush(); blank_string(strlen(str)); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* * Clear possible ECC errors * If not done, then we could get an interrupt later on when * exceptions are enabled. */ mtspr(mcsr, mfspr(mcsr)); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, ((val &~ DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF)); return; }
static void program_ecc(u32 start_address, u32 num_bytes, u32 tlb_word2_i_value) { u32 val; u32 current_addr = start_address; u32 size; int bytes_remaining; sync(); wait_ddr_idle(); /* * Because of 440EPx errata CHIP 11, we don't touch the last 256 * bytes of SDRAM. */ bytes_remaining = num_bytes - CONFIG_SYS_MEM_TOP_HIDE; /* * We have to write the ECC bytes by zeroing and flushing in smaller * steps, since the whole 256MByte takes too long for the external * watchdog. */ while (bytes_remaining > 0) { size = min((64 << 20), bytes_remaining); /* Write zero's to SDRAM */ dcbz_area(current_addr, size); /* Write modified dcache lines back to memory */ clean_dcache_range(current_addr, current_addr + size); current_addr += 64 << 20; bytes_remaining -= 64 << 20; WATCHDOG_RESET(); } sync(); wait_ddr_idle(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, ((val &~ DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF)); sync(); wait_ddr_idle(); }
static int is_ecc_enabled(void) { u32 val; mfsdram(DDR0_22, val); return 0x3 == DDR0_22_CTRL_RAW_DECODE(val); }
static void wait_ddr_idle(void) { u32 val; do { mfsdram(SDRAM_MCSTAT, val); } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); }
static void wait_init_complete(void) { u32 val; do { mfsdram(SDRAM0_MCSTS, val); } while (!(val & 0x80000000)); }
static u32 is_ecc_enabled(void) { u32 val; mfsdram(DDR0_22, val); val &= DDR0_22_CTRL_RAW_MASK; if (val) return 1; else return 0; }
void board_add_ram_info(int use_default) { u32 val; printf(" (ECC"); if (!is_ecc_enabled()) { printf(" not"); } printf(" enabled, %ld MHz", (2 * get_bus_freq(0)) / 1000000); mfsdram(DDR0_03, val); printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1); }
phys_size_t initdram(int board) { register uint reg; int tr1_bank1, tr1_bank2; /*-------------------------------------------------------------------- * Setup some default *------------------------------------------------------------------*/ mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ mtsdram(mem_clktr, 0x40000000); /* ?? */ mtsdram(mem_wddctr, 0x40000000); /* ?? */ /*clear this first, if the DDR is enabled by a debugger then you can not make changes. */ mtsdram(mem_cfg0, 0x00000000); /* Disable EEC */ /*-------------------------------------------------------------------- * Setup for board-specific specific mem *------------------------------------------------------------------*/ /* * Following for CAS Latency = 2.5 @ 133 MHz PLB */ mtsdram(mem_b0cr, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */ mtsdram(mem_b1cr, 0x080a4001); /* SDBA=0x080 128MB, Mode 3, enabled */ mtsdram(mem_tr0, 0x410a4012); /* ?? */ mtsdram(mem_rtr, 0x04080000); /* ?? */ mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM */ mtsdram(mem_cfg0, 0x30000000); /* Disable EEC */ udelay(400); /* Delay 200 usecs (min) */ /*-------------------------------------------------------------------- * Enable the controller, then wait for DCEN to complete *------------------------------------------------------------------*/ mtsdram(mem_cfg0, 0x80000000); /* Enable */ for (;;) { mfsdram(mem_mcsts, reg); if (reg & 0x80000000) break; } sdram_tr1_set(0x00000000, &tr1_bank1); sdram_tr1_set(0x08000000, &tr1_bank2); mtsdram(mem_tr1, (((tr1_bank1+tr1_bank2)/2) | 0x80800800)); return CFG_SDRAM_BANKS * (CFG_KBYTES_SDRAM * 1024); /* return bytes */ }
void board_add_ram_info(int use_default) { PPC4xx_SYS_INFO board_cfg; u32 val; if (is_ecc_enabled()) puts(" (ECC"); else puts(" (ECC not"); get_sys_info(&board_cfg); printf(" enabled, %ld MHz", (board_cfg.freqPLB * 2) / 1000000); mfsdram(DDR0_03, val); val = DDR0_03_CASLAT_DECODE(val); printf(", CL%d)", val); }
/************************************************************************* * fixed sdram init -- doesn't use serial presence detect. * * Assumes: 64 MB, non-ECC, non-registered * PLB @ 133 MHz * ************************************************************************/ long int fixed_sdram( void ) { uint reg; #if 1 /* test-only */ /*-------------------------------------------------------------------- * Setup some default *------------------------------------------------------------------*/ mtsdram( mem_uabba, 0x00000000 ); /* ubba=0 (default) */ mtsdram( mem_slio, 0x00000000 ); /* rdre=0 wrre=0 rarw=0 */ mtsdram( mem_devopt,0x00000000 ); /* dll=0 ds=0 (normal) */ mtsdram( mem_wddctr,0x40000000 ); /* wrcp=0 dcd=0 */ mtsdram( mem_clktr, 0x40000000 ); /* clkp=1 (90 deg wr) dcdt=0 */ /*-------------------------------------------------------------------- * Setup for board-specific specific mem *------------------------------------------------------------------*/ /* * Following for CAS Latency = 2.5 @ 133 MHz PLB */ mtsdram( mem_b0cr, 0x00082001 );/* SDBA=0x000, 64MB, Mode 2, enabled*/ mtsdram( mem_tr0, 0x410a4012 );/* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */ /* RA=10 RD=3 */ mtsdram( mem_tr1, 0x8080082f );/* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */ mtsdram( mem_rtr, 0x08200000 );/* Rate 15.625 ns @ 133 MHz PLB */ mtsdram( mem_cfg1, 0x00000000 );/* Self-refresh exit, disable PM */ udelay( 400 ); /* Delay 200 usecs (min) */ /*-------------------------------------------------------------------- * Enable the controller, then wait for DCEN to complete *------------------------------------------------------------------*/ mtsdram( mem_cfg0, 0x86000000 );/* DCEN=1, PMUD=1, 64-bit */ for(;;) { mfsdram( mem_mcsts, reg ); if( reg & 0x80000000 ) break; } return( 64 * 1024 * 1024 ); /* 64 MB */ #else return( 32 * 1024 * 1024 ); /* 64 MB */ #endif }
/* * void ecc_init() * * Description: * This routine initializes a range of DRAM ECC memory with known * data and enables ECC checking. * * TO DO: * - Improve performance by utilizing cache. * - Further generalize to make usable by other 4xx variants (e.g. * 440EPx, et al). * * Input(s): * start - A pointer to the start of memory covered by ECC requiring * initialization. * size - The size, in bytes, of the memory covered by ECC requiring * initialization. * * Output(s): * start - A pointer to the start of memory covered by ECC with * CFG_ECC_PATTERN written to all locations and ECC data * primed. * * Returns: * N/A */ void ecc_init(unsigned long * const start, unsigned long size) { const unsigned long pattern = CFG_ECC_PATTERN; unsigned long * const end = (unsigned long * const)((long)start + size); unsigned long * current = start; unsigned long mcopt1; long increment; if (start >= end) return; mfsdram(SDRAM_ECC_CFG, mcopt1); /* Enable ECC generation without checking or reporting */ mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) | SDRAM_ECC_CFG_MCHK_GEN)); increment = sizeof(u32); #if defined(CONFIG_440) /* * Look at the geometry of SDRAM (data width) to determine whether we * can skip words when writing. */ if ((mcopt1 & SDRAM_ECC_CFG_DMWD_MASK) != SDRAM_ECC_CFG_DMWD_32) increment = sizeof(u64); #endif /* defined(CONFIG_440) */ while (current < end) { *current = pattern; current = (unsigned long *)((long)current + increment); } /* Wait until the writes are finished. */ sync(); /* Enable ECC generation with checking and no reporting */ mtsdram(SDRAM_ECC_CFG, ((mcopt1 & ~SDRAM_ECC_CFG_MCHK_MASK) | SDRAM_ECC_CFG_MCHK_CHK)); }
/************************************************************************* * sdram_init -- doesn't use serial presence detect. * * Assumes: 256 MB, ECC, non-registered * PLB @ 133 MHz * ************************************************************************/ void sdram_init(void) { register uint reg; /*-------------------------------------------------------------------- * Setup some default *------------------------------------------------------------------*/ mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ mtsdram(mem_clktr, 0x40000000); /* ?? */ mtsdram(mem_wddctr, 0x40000000); /* ?? */ /*clear this first, if the DDR is enabled by a debugger then you can not make changes. */ mtsdram(mem_cfg0, 0x00000000); /* Disable EEC */ /*-------------------------------------------------------------------- * Setup for board-specific specific mem *------------------------------------------------------------------*/ /* * Following for CAS Latency = 2.5 @ 133 MHz PLB */ mtsdram(mem_b0cr, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */ mtsdram(mem_b1cr, 0x080a4001); /* SDBA=0x080 128MB, Mode 3, enabled */ mtsdram(mem_tr0, 0x410a4012); /* ?? */ mtsdram(mem_tr1, 0x8080080b); /* ?? */ mtsdram(mem_rtr, 0x04080000); /* ?? */ mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM */ mtsdram(mem_cfg0, 0x34000000); /* Disable EEC */ udelay(400); /* Delay 200 usecs (min) */ /*-------------------------------------------------------------------- * Enable the controller, then wait for DCEN to complete *------------------------------------------------------------------*/ mtsdram(mem_cfg0, 0x84000000); /* Enable */ for (;;) { mfsdram(mem_mcsts, reg); if (reg & 0x80000000) break; } }
static void ecc_init(ulong start, ulong size) { ulong current_addr; /* current byte address */ ulong end_addr; /* end of memory region */ ulong addr_inc; /* address skip between writes */ ulong cfg0_reg; /* for restoring ECC state */ /* * TODO: Enable dcache before running this test (speedup) */ mfsdram(mem_cfg0, cfg0_reg); mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_GEN); /* * look at geometry of SDRAM (data width) to determine whether we * can skip words when writing */ if ((cfg0_reg & SDRAM_CFG0_DRAMWDTH) == SDRAM_CFG0_DRAMWDTH_32) addr_inc = 4; else addr_inc = 8; current_addr = start; end_addr = start + size; while (current_addr < end_addr) { *((ulong *)current_addr) = 0x00000000; current_addr += addr_inc; } /* * TODO: Flush dcache and disable it again */ /* * Enable ecc checking and parity errors */ mtsdram(mem_cfg0, (cfg0_reg & ~SDRAM_CFG0_MEMCHK) | SDRAM_CFG0_MEMCHK_CHK); }
/************************************************************************* * fixed sdram init -- doesn't use serial presence detect. * * Assumes: 128 MB, non-ECC, non-registered * PLB @ 133 MHz * ************************************************************************/ long int fixed_sdram (void) { uint reg; /*-------------------------------------------------------------------- * Setup some default *------------------------------------------------------------------*/ mtsdram (SDRAM0_UABBA, 0x00000000); /* ubba=0 (default) */ mtsdram (SDRAM0_SLIO, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ mtsdram (SDRAM0_DEVOPT, 0x00000000); /* dll=0 ds=0 (normal) */ mtsdram (SDRAM0_WDDCTR, 0x00000000); /* wrcp=0 dcd=0 */ mtsdram (SDRAM0_CLKTR, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ /*-------------------------------------------------------------------- * Setup for board-specific specific mem *------------------------------------------------------------------*/ /* * Following for CAS Latency = 2.5 @ 133 MHz PLB */ mtsdram (SDRAM0_B0CR, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */ mtsdram (SDRAM0_TR0, 0x410a4012); /* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */ /* RA=10 RD=3 */ mtsdram (SDRAM0_TR1, 0x8080082f); /* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */ mtsdram (SDRAM0_RTR, 0x08200000); /* Rate 15.625 ns @ 133 MHz PLB */ mtsdram (SDRAM0_CFG1, 0x00000000); /* Self-refresh exit, disable PM */ udelay (400); /* Delay 200 usecs (min) */ /*-------------------------------------------------------------------- * Enable the controller, then wait for DCEN to complete *------------------------------------------------------------------*/ mtsdram (SDRAM0_CFG0, 0x86000000); /* DCEN=1, PMUD=1, 64-bit */ for (;;) { mfsdram (SDRAM0_MCSTS, reg); if (reg & 0x80000000) break; } return (128 * 1024 * 1024); /* 128 MB */ }
long int initdram(int board_type) { /* * Same as on Kilauea, Makalu generates exception 0x200 * (machine check) after trap_init() in board_init_f, * when SDRAM is initialized here (late) and d-cache is * used earlier as INIT_RAM. * So for now, initialize DDR2 in init.S very early and * also use it for INIT_RAM. Then this exception doesn't * occur. */ #if 0 u32 val; /* base=00000000, size=128MByte (5), mode=2 (n*10*4) */ mtsdram(SDRAM_MB0CF, 0x00005201); /* SET SDRAM_MB1CF - Not enabled */ mtsdram(SDRAM_MB1CF, 0x00000000); /* SET SDRAM_MB2CF - Not enabled */ mtsdram(SDRAM_MB2CF, 0x00000000); /* SET SDRAM_MB3CF - Not enabled */ mtsdram(SDRAM_MB3CF, 0x00000000); /* SDRAM_CLKTR: Adv Addr clock by 90 deg */ mtsdram(SDRAM_CLKTR, 0x80000000); /* Refresh Time register (0x30) Refresh every 7.8125uS */ mtsdram(SDRAM_RTR, 0x06180000); /* SDRAM_SDTR1 */ mtsdram(SDRAM_SDTR1, 0x80201000); /* SDRAM_SDTR2 */ mtsdram(SDRAM_SDTR2, 0x32204232); /* SDRAM_SDTR3 */ mtsdram(SDRAM_SDTR3, 0x080b0d1a); mtsdram(SDRAM_MMODE, 0x00000442); mtsdram(SDRAM_MEMODE, 0x00000404); /* SDRAM0_MCOPT1 (0X20) No ECC Gen */ mtsdram(SDRAM_MCOPT1, 0x04322000); /* NOP */ mtsdram(SDRAM_INITPLR0, 0xa8380000); /* precharge 3 DDR clock cycle */ mtsdram(SDRAM_INITPLR1, 0x81900400); /* EMR2 twr = 2tck */ mtsdram(SDRAM_INITPLR2, 0x81020000); /* EMR3 twr = 2tck */ mtsdram(SDRAM_INITPLR3, 0x81030000); /* EMR DLL ENABLE twr = 2tck */ mtsdram(SDRAM_INITPLR4, 0x81010404); /* MR w/ DLL reset * Note: 5 is CL. May need to be changed */ mtsdram(SDRAM_INITPLR5, 0x81000542); /* precharge 3 DDR clock cycle */ mtsdram(SDRAM_INITPLR6, 0x81900400); /* Auto-refresh trfc = 26tck */ mtsdram(SDRAM_INITPLR7, 0x8D080000); /* Auto-refresh trfc = 26tck */ mtsdram(SDRAM_INITPLR8, 0x8D080000); /* Auto-refresh */ mtsdram(SDRAM_INITPLR9, 0x8D080000); /* Auto-refresh */ mtsdram(SDRAM_INITPLR10, 0x8D080000); /* MRS - normal operation; wait 2 cycle (set wait to tMRD) */ mtsdram(SDRAM_INITPLR11, 0x81000442); mtsdram(SDRAM_INITPLR12, 0x81010780); mtsdram(SDRAM_INITPLR13, 0x81010400); mtsdram(SDRAM_INITPLR14, 0x00000000); mtsdram(SDRAM_INITPLR15, 0x00000000); /* SET MCIF0_CODT Die Termination On */ mtsdram(SDRAM_CODT, 0x0080f837); mtsdram(SDRAM_MODT0, 0x01800000); mtsdram(SDRAM_MODT1, 0x00000000); mtsdram(SDRAM_WRDTR, 0x00000000); /* SDRAM0_MCOPT2 (0X21) Start initialization */ mtsdram(SDRAM_MCOPT2, 0x20000000); /* Step 5 */ do { mfsdram(SDRAM_MCSTAT, val); } while ((val & SDRAM_MCSTAT_MIC_COMP) != SDRAM_MCSTAT_MIC_COMP); /* Step 6 */ /* SDRAM_DLCR */ mtsdram(SDRAM_DLCR, 0x030000a5); /* SDRAM_RDCC */ mtsdram(SDRAM_RDCC, 0x40000000); /* SDRAM_RQDC */ mtsdram(SDRAM_RQDC, 0x80000038); /* SDRAM_RFDC */ mtsdram(SDRAM_RFDC, 0x00000209); /* Enable memory controller */ mfsdram(SDRAM_MCOPT2, val); val |= SDRAM_MCOPT2_DCEN_ENABLE; mtsdram(SDRAM_MCOPT2, val); #endif return (CFG_MBYTES_SDRAM << 20); }
/************************************************************************* * * initdram -- 440EPx's DDR controller is a DENALI Core * ************************************************************************/ phys_size_t initdram (int board_type) { unsigned char data[2]; unsigned int chip, v, t, i, x, sz, ms, rr, rf, st; unsigned long speed; unsigned char mt, bl, cl, rk, tmp; /* memory type, burst length, cas latency, ranks */ unsigned char map[3] = { SPD_TAC0, SPD_TAC1, SPD_TAC2 }; #ifdef DEBUG unsigned int j; #endif chip = SPD_EEPROM_ADDRESS; debug("dram: about to probe chip 0x%x\n", chip); if(check_sane_spd(chip)){ printf("dram: nonexistent or unusable spd eeprom\n"); hang(); } #ifdef DEBUG debug("dram: raw"); for(j = 0; j < 64; j++){ if(i2c_read(chip, j, 1, data, 1) == 0){ debug("%c%02x", (j % 16) ? ' ' : '\n', data[0]); } } debug("\n"); #endif /* rushed dump from spd to ddr controller, calculations hardwired from sequoia and generally iffy */ if(i2c_read(chip, SPD_MEMORY_TYPE, 1, data, 1) != 0){ return 0; } mt = data[0]; switch(mt){ case SPD_MEMORY_TYPE_DDR2_SDRAM : debug("dram: ddr2 memory\n"); break; /* case SPD_MEMORY_TYPE_DDR_SDRAM : */ default : printf("dram: unsupported memory type 0x%x\n", mt); return 0; } speed = get_bus_freq(0); debug("dram: bus speed %luHz\n", speed); if(i2c_read(chip, SPD_REFRESH_RATE, 1, data, 1) != 0){ return 0; } rr = decode_refresh(data[0]); debug("dram: refresh rate %ups\n", rr); xmtsdram(DDR0_02, DDR0_02_START_OFF); mfsdram(DDR0_02, ms); /* gives us the maximum dimensions the controller can do, used later */ debug("dram: controller caps 0x%08x\n", ms); /* calibration values as recommended */ xmtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | DDR0_00_DLL_START_POINT_ENCODE(0xa)); /* set as required, possibly could set up interrupt masks */ xmtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x1) | DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0)); v = 0; v |= DDR0_03_INITAREF_ENCODE(0x2); /* WARNING: no idea how many autorefresh commands needed during initialisation */ if(i2c_read(chip, SPD_BURST_LENGTHS, 1, data, 1) != 0){ return 0; } bl = ((mt != SPD_MEMORY_TYPE_DDR2_SDRAM) && (data[0] & SPD_BURST_LENGTH_8)) ? 8 : 4; debug("dram: burst length caps=0x%x, chosen=%d\n", data[0], bl); v |= DDR0_03_BSTLEN_ENCODE((bl == 8) ? 0x3 : 0x2); if(i2c_read(chip, SPD_CAS_LATENCIES, 1, data, 1) != 0){ return 0; } cl = 0; tmp = data[0]; debug("dram: latency choices 0x%x\n", tmp); /* could use a less agressive mode by quitting for a lower x */ for(i = 7, x = 0; (i >= 2) && (x < 3); i--){ if(tmp & (0x1 << i)){ debug("dram: can do cl=%d\n", i); if(i2c_read(chip, map[x] + 1, 1, data, 1) != 0){ return 0; } t = ps2cycles(speed, (((data[0] >> 4) & 0xf) * 100) + ((data[0] & 0xf) * 10), "minclock"); if(t > 0){ debug("dram: clock too fast for cl-%d\n", x); break; } cl = i; x++; } }
static void program_ecc_addr(unsigned long start_address, unsigned long num_bytes, unsigned long tlb_word2_i_value) { unsigned long current_address; unsigned long end_address; unsigned long address_increment; unsigned long mcopt1; char str[] = "ECC generation -"; char slash[] = "\\|/-\\|/-"; int loop = 0; int loopi = 0; current_address = start_address; mfsdram(SDRAM_MCOPT1, mcopt1); if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { mtsdram(SDRAM_MCOPT1, (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN); sync(); eieio(); wait_ddr_idle(); puts(str); #ifdef CONFIG_440 if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) { #endif /* ECC bit set method for non-cached memory */ if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32) address_increment = 4; else address_increment = SDRAM_DATA_ALT_WIDTH; end_address = current_address + num_bytes; while (current_address < end_address) { *((unsigned long *)current_address) = 0; current_address += address_increment; if ((loop++ % (2 << 20)) == 0) { putc('\b'); putc(slash[loopi++ % 8]); } } #ifdef CONFIG_440 } else { /* ECC bit set method for cached memory */ dcbz_area(start_address, num_bytes); /* Write modified dcache lines back to memory */ clean_dcache_range(start_address, start_address + num_bytes); } #endif /* CONFIG_440 */ blank_string(strlen(str)); sync(); eieio(); wait_ddr_idle(); /* clear ECC error repoting registers */ mtsdram(SDRAM_ECCES, 0xffffffff); mtdcr(0x4c, 0xffffffff); mtsdram(SDRAM_MCOPT1, (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP); sync(); eieio(); wait_ddr_idle(); } }
static void denali_sdram_register_dump(void) { unsigned int sdram_data; printf("\n Register Dump:\n"); mfsdram(DDR0_00, sdram_data); printf(" DDR0_00 = 0x%08X", sdram_data); mfsdram(DDR0_01, sdram_data); printf(" DDR0_01 = 0x%08X\n", sdram_data); mfsdram(DDR0_02, sdram_data); printf(" DDR0_02 = 0x%08X", sdram_data); mfsdram(DDR0_03, sdram_data); printf(" DDR0_03 = 0x%08X\n", sdram_data); mfsdram(DDR0_04, sdram_data); printf(" DDR0_04 = 0x%08X", sdram_data); mfsdram(DDR0_05, sdram_data); printf(" DDR0_05 = 0x%08X\n", sdram_data); mfsdram(DDR0_06, sdram_data); printf(" DDR0_06 = 0x%08X", sdram_data); mfsdram(DDR0_07, sdram_data); printf(" DDR0_07 = 0x%08X\n", sdram_data); mfsdram(DDR0_08, sdram_data); printf(" DDR0_08 = 0x%08X", sdram_data); mfsdram(DDR0_09, sdram_data); printf(" DDR0_09 = 0x%08X\n", sdram_data); mfsdram(DDR0_10, sdram_data); printf(" DDR0_10 = 0x%08X", sdram_data); mfsdram(DDR0_11, sdram_data); printf(" DDR0_11 = 0x%08X\n", sdram_data); mfsdram(DDR0_12, sdram_data); printf(" DDR0_12 = 0x%08X", sdram_data); mfsdram(DDR0_14, sdram_data); printf(" DDR0_14 = 0x%08X\n", sdram_data); mfsdram(DDR0_17, sdram_data); printf(" DDR0_17 = 0x%08X", sdram_data); mfsdram(DDR0_18, sdram_data); printf(" DDR0_18 = 0x%08X\n", sdram_data); mfsdram(DDR0_19, sdram_data); printf(" DDR0_19 = 0x%08X", sdram_data); mfsdram(DDR0_20, sdram_data); printf(" DDR0_20 = 0x%08X\n", sdram_data); mfsdram(DDR0_21, sdram_data); printf(" DDR0_21 = 0x%08X", sdram_data); mfsdram(DDR0_22, sdram_data); printf(" DDR0_22 = 0x%08X\n", sdram_data); mfsdram(DDR0_23, sdram_data); printf(" DDR0_23 = 0x%08X", sdram_data); mfsdram(DDR0_24, sdram_data); printf(" DDR0_24 = 0x%08X\n", sdram_data); mfsdram(DDR0_25, sdram_data); printf(" DDR0_25 = 0x%08X", sdram_data); mfsdram(DDR0_26, sdram_data); printf(" DDR0_26 = 0x%08X\n", sdram_data); mfsdram(DDR0_27, sdram_data); printf(" DDR0_27 = 0x%08X", sdram_data); mfsdram(DDR0_28, sdram_data); printf(" DDR0_28 = 0x%08X\n", sdram_data); mfsdram(DDR0_31, sdram_data); printf(" DDR0_31 = 0x%08X", sdram_data); mfsdram(DDR0_32, sdram_data); printf(" DDR0_32 = 0x%08X\n", sdram_data); mfsdram(DDR0_33, sdram_data); printf(" DDR0_33 = 0x%08X", sdram_data); mfsdram(DDR0_34, sdram_data); printf(" DDR0_34 = 0x%08X\n", sdram_data); mfsdram(DDR0_35, sdram_data); printf(" DDR0_35 = 0x%08X", sdram_data); mfsdram(DDR0_36, sdram_data); printf(" DDR0_36 = 0x%08X\n", sdram_data); mfsdram(DDR0_37, sdram_data); printf(" DDR0_37 = 0x%08X", sdram_data); mfsdram(DDR0_38, sdram_data); printf(" DDR0_38 = 0x%08X\n", sdram_data); mfsdram(DDR0_39, sdram_data); printf(" DDR0_39 = 0x%08X", sdram_data); mfsdram(DDR0_40, sdram_data); printf(" DDR0_40 = 0x%08X\n", sdram_data); mfsdram(DDR0_41, sdram_data); printf(" DDR0_41 = 0x%08X", sdram_data); mfsdram(DDR0_42, sdram_data); printf(" DDR0_42 = 0x%08X\n", sdram_data); mfsdram(DDR0_43, sdram_data); printf(" DDR0_43 = 0x%08X", sdram_data); mfsdram(DDR0_44, sdram_data); printf(" DDR0_44 = 0x%08X\n", sdram_data); }
/*----------------------------------------------------------------------------- * Function: initdram * Description: Configures SDRAM memory banks for DDR operation. * Auto Memory Configuration option reads the DDR SDRAM EEPROMs * via the IIC bus and then configures the DDR SDRAM memory * banks appropriately. If Auto Memory Configuration is * not used, it is assumed that no DIMM is plugged *-----------------------------------------------------------------------------*/ phys_size_t initdram(int board_type) { unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; unsigned long dimm_ranks[MAXDIMMS]; unsigned long ranks; unsigned long rows; unsigned long banks; unsigned long cols; unsigned long width; unsigned long const sdram_freq = get_bus_freq(0); unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */ unsigned long cas_latency = 0; /* to quiet initialization warning */ unsigned long dram_size; debug("\nEntering initdram()\n"); /*------------------------------------------------------------------ * Stop the DDR-SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_02, DDR0_02_START_ENCODE(0)); /* * Make sure I2C controller is initialized * before continuing. */ /* switch to correct I2C bus */ I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); /*------------------------------------------------------------------ * Clear out the serial presence detect buffers. * Perform IIC reads from the dimm. Fill in the spds. * Check to see if the dimm slots are populated *-----------------------------------------------------------------*/ get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Check the frequency supported for the dimms plugged. *-----------------------------------------------------------------*/ check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /*------------------------------------------------------------------ * Check and get size information. *-----------------------------------------------------------------*/ get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks, &cols, &width); /*------------------------------------------------------------------ * Check the voltage type for the dimms plugged. *-----------------------------------------------------------------*/ check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks); /*------------------------------------------------------------------ * Program registers for SDRAM controller. *-----------------------------------------------------------------*/ mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | DDR0_00_DLL_START_POINT_DECODE(0x0A)); mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) | DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) | DDR0_01_INT_MASK_ENCODE(0xFF)); program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, rows, &cas_latency); program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); /* * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia * board SDRAM, but may be overly conservative. */ mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | DDR0_07_TFAW_ENCODE(13) | DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | DDR0_07_AREFRESH_ENCODE(0)); mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) | DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) | DDR0_08_DDRII_ENCODE(1)); mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) | DDR0_09_RTT_0_ENCODE(0x1) | DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) | DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20)); program_ddr0_10(dimm_ranks, ranks); program_ddr0_11(sdram_freq); mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3)); mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) | DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) | DDR0_14_REG_DIMM_ENABLE_ENCODE(0)); mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) | DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) | DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY)); mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) | DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS)); mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) | DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS)); program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width); mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) | DDR0_23_FWC_ENCODE(0)); program_ddr0_24(ranks); program_ddr0_26(sdram_freq); program_ddr0_27(sdram_freq); mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) | DDR0_28_EMRS2_DATA_ENCODE(0x0000)); mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000)); mtsdram(DDR0_42, DDR0_42_ADDR_PINS_DECODE(14 - rows) | DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency)); program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, cols, banks); program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); denali_sdram_register_dump(); dram_size = (width >= 64) ? 8 : 4; dram_size *= 1 << cols; dram_size *= banks; dram_size *= 1 << rows; dram_size *= ranks; debug("dram_size = %lu\n", dram_size); /* Start the SDRAM controler */ mtsdram(DDR0_02, DDR0_02_START_ENCODE(1)); denali_wait_for_dlllock(); #if defined(CONFIG_DDR_DATA_EYE) /* * Map the first 1 MiB of memory in the TLB, and perform the data eye * search. */ program_tlb(0, CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE); denali_core_search_data_eye(); denali_sdram_register_dump(); remove_tlb(CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE); #endif #if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, 0); sync(); /* Zero the memory */ debug("Zeroing SDRAM..."); #if defined(CONFIG_SYS_MEM_TOP_HIDE) dcbz_area(CONFIG_SYS_SDRAM_BASE, dram_size - CONFIG_SYS_MEM_TOP_HIDE); #else #error Please define CONFIG_SYS_MEM_TOP_HIDE (see README) in your board config file #endif /* Write modified dcache lines back to memory */ clean_dcache_range(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE + dram_size - CONFIG_SYS_MEM_TOP_HIDE); debug("Completed\n"); sync(); remove_tlb(CONFIG_SYS_SDRAM_BASE, dram_size); #if defined(CONFIG_DDR_ECC) /* * If ECC is enabled, clear and enable interrupts */ if (is_ecc_enabled()) { u32 val; sync(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF); #if defined(CONFIG_DDR_DATA_EYE) /* * Running denali_core_search_data_eye() when ECC is enabled * causes non-ECC machine checks. This clears them. */ print_mcsr(); mtspr(SPRN_MCSR, mfspr(SPRN_MCSR)); print_mcsr(); #endif sync(); } #endif /* defined(CONFIG_DDR_ECC) */ #endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE); return dram_size; }
static void program_ecc(u32 start_address, u32 num_bytes, u32 tlb_word2_i_value) { u32 current_address; u32 end_address; u32 address_increment; u32 val; char str[] = "ECC generation -"; char slash[] = "\\|/-\\|/-"; int loop = 0; int loopi = 0; current_address = start_address; sync(); eieio(); wait_ddr_idle(); if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) { /* ECC bit set method for non-cached memory */ address_increment = 4; end_address = current_address + num_bytes; puts(str); while (current_address < end_address) { *((u32 *)current_address) = 0x00000000; current_address += address_increment; if ((loop++ % (2 << 20)) == 0) { putc('\b'); putc(slash[loopi++ % 8]); } } blank_string(strlen(str)); } else { /* ECC bit set method for cached memory */ #if 0 /* test-only: will remove this define later, when ECC problems are solved! */ /* * Some boards (like lwmon5) need to preserve the memory * content upon ECC generation (for the log-buffer). * Therefore we don't fill the memory with a pattern or * just zero it, but write the same values back that are * already in the memory cells. */ address_increment = CFG_CACHELINE_SIZE; end_address = current_address + num_bytes; current_address = start_address; while (current_address < end_address) { /* * TODO: Th following sequence doesn't work correctly. * Just invalidating and flushing the cache doesn't * seem to trigger the re-write of the memory. */ ppcDcbi(current_address); ppcDcbf(current_address); current_address += CFG_CACHELINE_SIZE; } #else dcbz_area(start_address, num_bytes); dflush(); #endif } sync(); eieio(); wait_ddr_idle(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); /* Set 'int_mask' parameter to functionnal value */ mfsdram(DDR0_01, val); mtsdram(DDR0_01, ((val &~ DDR0_01_INT_MASK_MASK) | DDR0_01_INT_MASK_ALL_OFF)); sync(); eieio(); wait_ddr_idle(); }