/*
* cpu/ppc4xx/44x_spd_ddr2.c
* This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
- * DDR2 controller (non Denali Core). Those are 440SP/SPe.
+ * DDR2 controller (non Denali Core). Those currently are:
*
+ * 405: 405EX(r)
+ * 440/460: 440SP/440SPe/460EX/460GT
+ *
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ * Grant Erickson <gerickson@nuovations.com>
+
* (C) Copyright 2007-2008
* Stefan Roese, DENX Software Engineering, sr@denx.de.
*
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
#if defined(CONFIG_SPD_EEPROM) && \
- (defined(CONFIG_440SP) || defined(CONFIG_440SPE))
+ (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
/*-----------------------------------------------------------------------------+
* Defines
static void ppc440sp_sdram_register_dump(void);
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void dcbz_area(u32 start_address, u32 num_bytes);
-void dflush(void);
static u32 mfdcr_any(u32 dcr)
{
ppc440sp_sdram_register_dump();
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+
return dram_size;
}
if (num_banks == 4)
ind = 0;
else
- ind = 5;
+ ind = 5 << 8;
switch (num_col_addr) {
case 0x08:
mode |= (SDRAM_BXCF_M_AM_0 + ind);
unsigned long baseadd_size;
unsigned long i;
unsigned long bank_0_populated = 0;
+ unsigned long total_size = 0;
/*------------------------------------------------------------------
* Reset the rank_base_address.
* Set the sizes
*-----------------------------------------------------------------*/
baseadd_size = 0;
- rank_size_bytes = 4 * 1024 * 1024 * rank_size_id;
switch (rank_size_id) {
+ case 0x01:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+ total_size = 1024;
+ break;
case 0x02:
- baseadd_size |= SDRAM_RXBAS_SDSZ_8;
+ baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+ total_size = 2048;
break;
case 0x04:
- baseadd_size |= SDRAM_RXBAS_SDSZ_16;
+ baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+ total_size = 4096;
break;
case 0x08:
baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+ total_size = 32;
break;
case 0x10:
baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+ total_size = 64;
break;
case 0x20:
baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+ total_size = 128;
break;
case 0x40:
baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+ total_size = 256;
break;
case 0x80:
baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+ total_size = 512;
break;
default:
printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
printf("Replace the DIMM module with a supported DIMM.\n\n");
spd_ddr_init_hang ();
}
+ rank_size_bytes = total_size << 20;
if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
bank_0_populated = 1;
}
}
}
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ /*
+ * Enable high bandwidth access on 460EX/GT.
+ * This should/could probably be done on other
+ * PPC's too, like 440SPe.
+ * This is currently not used, but with this setup
+ * it is possible to use it later on in e.g. the Linux
+ * EMAC driver for performance gain.
+ */
+ mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+ mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+#endif
}
/*-----------------------------------------------------------------------------+
} else {
/* ECC bit set method for cached memory */
dcbz_area(start_address, num_bytes);
- dflush();
+ /* Write modified dcache lines back to memory */
+ clean_dcache_range(start_address, start_address + num_bytes);
}
blank_string(strlen(str));
dcr_data = mfdcr(SDRAM_R3BAS);
printf(" MQ3_B0BAS = 0x%08X\n", dcr_data);
}
-#else
+#else /* !defined(DEBUG) */
static void ppc440sp_sdram_register_dump(void)
{
}
-#endif
-#endif /* CONFIG_SPD_EEPROM */
+#endif /* defined(DEBUG) */
+#elif defined(CONFIG_405EX)
+/*-----------------------------------------------------------------------------
+ * Function: initdram
+ * Description: Configures the PPC405EX(r) DDR1/DDR2 SDRAM memory
+ * banks. The configuration is performed using static, compile-
+ * time parameters.
+ *---------------------------------------------------------------------------*/
+long initdram(int board_type)
+{
+ /*
+ * Only run this SDRAM init code once. For NAND booting
+ * targets like Kilauea, we call initdram() early from the
+ * 4k NAND booting image (CONFIG_NAND_SPL) from nand_boot().
+ * Later on the NAND U-Boot image runs (CONFIG_NAND_U_BOOT)
+ * which calls initdram() again. This time the controller
+ * mustn't be reconfigured again since we're already running
+ * from SDRAM.
+ */
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+ unsigned long val;
+
+ /* Set Memory Bank Configuration Registers */
+
+ mtsdram(SDRAM_MB0CF, CFG_SDRAM0_MB0CF);
+ mtsdram(SDRAM_MB1CF, CFG_SDRAM0_MB1CF);
+ mtsdram(SDRAM_MB2CF, CFG_SDRAM0_MB2CF);
+ mtsdram(SDRAM_MB3CF, CFG_SDRAM0_MB3CF);
+
+ /* Set Memory Clock Timing Register */
+
+ mtsdram(SDRAM_CLKTR, CFG_SDRAM0_CLKTR);
+
+ /* Set Refresh Time Register */
+
+ mtsdram(SDRAM_RTR, CFG_SDRAM0_RTR);
+
+ /* Set SDRAM Timing Registers */
+
+ mtsdram(SDRAM_SDTR1, CFG_SDRAM0_SDTR1);
+ mtsdram(SDRAM_SDTR2, CFG_SDRAM0_SDTR2);
+ mtsdram(SDRAM_SDTR3, CFG_SDRAM0_SDTR3);
+
+ /* Set Mode and Extended Mode Registers */
+
+ mtsdram(SDRAM_MMODE, CFG_SDRAM0_MMODE);
+ mtsdram(SDRAM_MEMODE, CFG_SDRAM0_MEMODE);
+
+ /* Set Memory Controller Options 1 Register */
+
+ mtsdram(SDRAM_MCOPT1, CFG_SDRAM0_MCOPT1);
+
+ /* Set Manual Initialization Control Registers */
+
+ mtsdram(SDRAM_INITPLR0, CFG_SDRAM0_INITPLR0);
+ mtsdram(SDRAM_INITPLR1, CFG_SDRAM0_INITPLR1);
+ mtsdram(SDRAM_INITPLR2, CFG_SDRAM0_INITPLR2);
+ mtsdram(SDRAM_INITPLR3, CFG_SDRAM0_INITPLR3);
+ mtsdram(SDRAM_INITPLR4, CFG_SDRAM0_INITPLR4);
+ mtsdram(SDRAM_INITPLR5, CFG_SDRAM0_INITPLR5);
+ mtsdram(SDRAM_INITPLR6, CFG_SDRAM0_INITPLR6);
+ mtsdram(SDRAM_INITPLR7, CFG_SDRAM0_INITPLR7);
+ mtsdram(SDRAM_INITPLR8, CFG_SDRAM0_INITPLR8);
+ mtsdram(SDRAM_INITPLR9, CFG_SDRAM0_INITPLR9);
+ mtsdram(SDRAM_INITPLR10, CFG_SDRAM0_INITPLR10);
+ mtsdram(SDRAM_INITPLR11, CFG_SDRAM0_INITPLR11);
+ mtsdram(SDRAM_INITPLR12, CFG_SDRAM0_INITPLR12);
+ mtsdram(SDRAM_INITPLR13, CFG_SDRAM0_INITPLR13);
+ mtsdram(SDRAM_INITPLR14, CFG_SDRAM0_INITPLR14);
+ mtsdram(SDRAM_INITPLR15, CFG_SDRAM0_INITPLR15);
+
+ /* Set On-Die Termination Registers */
+
+ mtsdram(SDRAM_CODT, CFG_SDRAM0_CODT);
+ mtsdram(SDRAM_MODT0, CFG_SDRAM0_MODT0);
+ mtsdram(SDRAM_MODT1, CFG_SDRAM0_MODT1);
+
+ /* Set Write Timing Register */
+
+ mtsdram(SDRAM_WRDTR, CFG_SDRAM0_WRDTR);
+
+ /*
+ * Start Initialization by SDRAM0_MCOPT2[SREN] = 0 and
+ * SDRAM0_MCOPT2[IPTR] = 1
+ */
+
+ mtsdram(SDRAM_MCOPT2, (SDRAM_MCOPT2_SREN_EXIT |
+ SDRAM_MCOPT2_IPTR_EXECUTE));
+
+ /*
+ * Poll SDRAM0_MCSTAT[MIC] for assertion to indicate the
+ * completion of initialization.
+ */
+
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_MIC_MASK) != SDRAM_MCSTAT_MIC_COMP);
+
+ /* Set Delay Control Registers */
+
+ mtsdram(SDRAM_DLCR, CFG_SDRAM0_DLCR);
+ mtsdram(SDRAM_RDCC, CFG_SDRAM0_RDCC);
+ mtsdram(SDRAM_RQDC, CFG_SDRAM0_RQDC);
+ mtsdram(SDRAM_RFDC, CFG_SDRAM0_RFDC);
+
+ /*
+ * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1:
+ */
+
+ mfsdram(SDRAM_MCOPT2, val);
+ mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE);
+
+#if defined(CONFIG_DDR_ECC)
+ ecc_init(CFG_SDRAM_BASE, CFG_MBYTES_SDRAM << 20);
+#endif /* defined(CONFIG_DDR_ECC) */
+#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+
+ return (CFG_MBYTES_SDRAM << 20);
+}
+#endif /* defined(CONFIG_SPD_EEPROM) && defined(CONFIG_440SP) || ... */