From: York Sun Date: Mon, 30 Sep 2013 16:22:09 +0000 (-0700) Subject: Driver/DDR: Moving Freescale DDR driver to a common driver X-Git-Tag: v2014.01-rc2~57^2~9 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5614e71b4956c579cd4419b958b33fa6316eaa92;p=u-boot Driver/DDR: Moving Freescale DDR driver to a common driver Freescale DDR driver has been used for mpc83xx, mpc85xx, mpc86xx SoCs. The similar DDR controllers will be used for ARM-based SoCs. Signed-off-by: York Sun --- diff --git a/Makefile b/Makefile index b8713a4935..2ad1d37a62 100644 --- a/Makefile +++ b/Makefile @@ -267,6 +267,7 @@ LIBS-y += drivers/power/ \ drivers/power/battery/ LIBS-y += drivers/spi/ LIBS-$(CONFIG_FMAN_ENET) += drivers/net/fm/ +LIBS-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/ LIBS-y += drivers/serial/ LIBS-y += drivers/usb/eth/ LIBS-y += drivers/usb/gadget/ diff --git a/README b/README index c97ff0af0b..49f4b3af2f 100644 --- a/README +++ b/README @@ -423,16 +423,47 @@ The following options need to be configured: CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT This value denotes start offset of DSP CCSR space. - CONFIG_SYS_FSL_DDR_EMU - Specify emulator support for DDR. Some DDR features such as - deskew training are not available. - - Generic CPU options: CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN Defines the endianess of the CPU. Implementation of those values is arch specific. + CONFIG_SYS_FSL_DDR + Freescale DDR driver in use. This type of DDR controller is + found in mpc83xx, mpc85xx, mpc86xx as well as some ARM core + SoCs. + + CONFIG_SYS_FSL_DDR_ADDR + Freescale DDR memory-mapped register base. + + CONFIG_SYS_FSL_DDR_EMU + Specify emulator support for DDR. Some DDR features such as + deskew training are not available. + + CONFIG_SYS_FSL_DDRC_GEN1 + Freescale DDR1 controller. + + CONFIG_SYS_FSL_DDRC_GEN2 + Freescale DDR2 controller. + + CONFIG_SYS_FSL_DDRC_GEN3 + Freescale DDR3 controller. + + CONFIG_SYS_FSL_DDR1 + Board config to use DDR1. It can be enabled for SoCs with + Freescale DDR1 or DDR2 controllers, depending on the board + implemetation. + + CONFIG_SYS_FSL_DDR2 + Board config to use DDR2. It can be eanbeld for SoCs with + Freescale DDR2 or DDR3 controllers, depending on the board + implementation. + + CONFIG_SYS_FSL_DDR3 + Board config to use DDR3. It can be enabled for SoCs with + Freescale DDR3 controllers. + - Intel Monahans options: CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO @@ -3182,7 +3213,7 @@ FIT uImage format: CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT Set for the SPL on PPC mpc8xxx targets, support for - arch/powerpc/cpu/mpc8xxx/ddr/libddr.o in SPL binary. + drivers/ddr/fsl/libddr.o in SPL binary. CONFIG_SPL_COMMON_INIT_DDR Set for common ddr init with serial presence detect in diff --git a/arch/powerpc/cpu/mpc83xx/Makefile b/arch/powerpc/cpu/mpc83xx/Makefile index d3f7001478..c345dd6ae6 100644 --- a/arch/powerpc/cpu/mpc83xx/Makefile +++ b/arch/powerpc/cpu/mpc83xx/Makefile @@ -38,11 +38,11 @@ obj-$(CONFIG_OF_LIBFDT) += fdt.o # Stub implementations of cache management functions for USB obj-y += cache.o -ifdef CONFIG_FSL_DDR2 -obj-$(CONFIG_MPC8349) += ../mpc85xx/ddr-gen2.o +ifdef CONFIG_SYS_FSL_DDR2 +obj-$(CONFIG_MPC8349) += $(SRCTREE)/drivers/ddr/fsl/mpc85xx_ddr_gen2.o else obj-y += spd_sdram.o endif -obj-$(CONFIG_FSL_DDR2) += law.o +obj-$(CONFIG_SYS_FSL_DDR2) += law.o endif # not minimal diff --git a/arch/powerpc/cpu/mpc83xx/ecc.c b/arch/powerpc/cpu/mpc83xx/ecc.c index 120b37ba63..6b7f72aa7d 100644 --- a/arch/powerpc/cpu/mpc83xx/ecc.c +++ b/arch/powerpc/cpu/mpc83xx/ecc.c @@ -15,7 +15,7 @@ void ecc_print_status(void) { immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; -#ifdef CONFIG_FSL_DDR2 +#ifdef CONFIG_SYS_FSL_DDR2 ccsr_ddr_t *ddr = &immap->ddr; #else ddr83xx_t *ddr = &immap->ddr; @@ -99,7 +99,7 @@ void ecc_print_status(void) int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; -#ifdef CONFIG_FSL_DDR2 +#ifdef CONFIG_SYS_FSL_DDR2 ccsr_ddr_t *ddr = &immap->ddr; #else ddr83xx_t *ddr = &immap->ddr; diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile index a34014f305..91c8402047 100644 --- a/arch/powerpc/cpu/mpc85xx/Makefile +++ b/arch/powerpc/cpu/mpc85xx/Makefile @@ -29,51 +29,6 @@ obj-$(CONFIG_MP) += release.o obj-$(CONFIG_CMD_ERRATA) += cmd_errata.o obj-$(CONFIG_CPM2) += commproc.o -# supports ddr1 -obj-$(CONFIG_MPC8540) += ddr-gen1.o -obj-$(CONFIG_MPC8560) += ddr-gen1.o -obj-$(CONFIG_MPC8541) += ddr-gen1.o -obj-$(CONFIG_MPC8555) += ddr-gen1.o - -# supports ddr1/2 -obj-$(CONFIG_MPC8548) += ddr-gen2.o -obj-$(CONFIG_MPC8568) += ddr-gen2.o -obj-$(CONFIG_MPC8544) += ddr-gen2.o - -# supports ddr1/2/3 -obj-$(CONFIG_PPC_C29X) += ddr-gen3.o -obj-$(CONFIG_MPC8572) += ddr-gen3.o -obj-$(CONFIG_MPC8536) += ddr-gen3.o -obj-$(CONFIG_MPC8569) += ddr-gen3.o -obj-$(CONFIG_P1010) += ddr-gen3.o -obj-$(CONFIG_P1011) += ddr-gen3.o -obj-$(CONFIG_P1012) += ddr-gen3.o -obj-$(CONFIG_P1013) += ddr-gen3.o -obj-$(CONFIG_P1014) += ddr-gen3.o -obj-$(CONFIG_P1020) += ddr-gen3.o -obj-$(CONFIG_P1021) += ddr-gen3.o -obj-$(CONFIG_P1022) += ddr-gen3.o -obj-$(CONFIG_P1023) += ddr-gen3.o -obj-$(CONFIG_P1024) += ddr-gen3.o -obj-$(CONFIG_P1025) += ddr-gen3.o -obj-$(CONFIG_P2010) += ddr-gen3.o -obj-$(CONFIG_P2020) += ddr-gen3.o -obj-$(CONFIG_PPC_P2041) += ddr-gen3.o -obj-$(CONFIG_PPC_P3041) += ddr-gen3.o -obj-$(CONFIG_PPC_P4080) += ddr-gen3.o -obj-$(CONFIG_PPC_P5020) += ddr-gen3.o -obj-$(CONFIG_PPC_P5040) += ddr-gen3.o -obj-$(CONFIG_PPC_T4240) += ddr-gen3.o -obj-$(CONFIG_PPC_T4160) += ddr-gen3.o -obj-$(CONFIG_PPC_B4420) += ddr-gen3.o -obj-$(CONFIG_PPC_B4860) += ddr-gen3.o -obj-$(CONFIG_BSC9131) += ddr-gen3.o -obj-$(CONFIG_BSC9132) += ddr-gen3.o -obj-$(CONFIG_PPC_T1040) += ddr-gen3.o -obj-$(CONFIG_PPC_T1042) += ddr-gen3.o -obj-$(CONFIG_PPC_T1020) += ddr-gen3.o -obj-$(CONFIG_PPC_T1022) += ddr-gen3.o - obj-$(CONFIG_CPM2) += ether_fcc.o obj-$(CONFIG_OF_LIBFDT) += fdt.o obj-$(CONFIG_FSL_CORENET) += liodn.o diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c index 1a0196c7c4..552acc6879 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu.c +++ b/arch/powerpc/cpu/mpc85xx/cpu.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -453,21 +453,21 @@ static void dump_spd_ddr_reg(void) for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { switch (i) { case 0: - ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ddr[i] = (void *)CONFIG_SYS_FSL_DDR_ADDR; break; -#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) +#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: - ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR; + ddr[i] = (void *)CONFIG_SYS_FSL_DDR2_ADDR; break; #endif -#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) +#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) case 2: - ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR; + ddr[i] = (void *)CONFIG_SYS_FSL_DDR3_ADDR; break; #endif -#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) case 3: - ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR; + ddr[i] = (void *)CONFIG_SYS_FSL_DDR4_ADDR; break; #endif default: diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c deleted file mode 100644 index 4dd8c0b5bf..0000000000 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include - -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) -#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL -#endif - -void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step) -{ - unsigned int i; - volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; - - if (ctrl_num != 0) { - printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); - return; - } - - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (i == 0) { - out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs0_config, regs->cs[i].config); - - } else if (i == 1) { - out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs1_config, regs->cs[i].config); - - } else if (i == 2) { - out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs2_config, regs->cs[i].config); - - } else if (i == 3) { - out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs3_config, regs->cs[i].config); - } - } - - out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); - out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); -#if defined(CONFIG_MPC8555) || defined(CONFIG_MPC8541) - out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); -#endif - - /* - * 200 painful micro-seconds must elapse between - * the DDR clock setup and the DDR config enable. - */ - udelay(200); - asm volatile("sync;isync"); - - out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); - - asm("sync;isync;msync"); - udelay(500); -} - -#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) -/* - * Initialize all of memory for ECC, then enable errors. - */ - -void -ddr_enable_ecc(unsigned int dram_size) -{ - volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); - - dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size); - - /* - * Enable errors for ECC. - */ - debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable); - ddr->err_disable = 0x00000000; - asm("sync;isync;msync"); - debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable); -} - -#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */ diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c deleted file mode 100644 index 542bc84acf..0000000000 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2008-2011 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) -#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL -#endif - -void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step) -{ - unsigned int i; - ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; - -#if defined(CONFIG_SYS_FSL_ERRATUM_NMG_DDR120) && defined(CONFIG_MPC85xx) - ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); - uint svr; -#endif - - if (ctrl_num) { - printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); - return; - } - -#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_DDR120 - /* - * Set the DDR IO receiver to an acceptable bias point. - * Fixed in Rev 2.1. - */ - svr = get_svr(); - if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0)) { - if ((regs->ddr_sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) == - SDRAM_CFG_SDRAM_TYPE_DDR2) - out_be32(&gur->ddrioovcr, 0x90000000); - else - out_be32(&gur->ddrioovcr, 0xA8000000); - } -#endif - - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (i == 0) { - out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs0_config, regs->cs[i].config); - - } else if (i == 1) { - out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs1_config, regs->cs[i].config); - - } else if (i == 2) { - out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs2_config, regs->cs[i].config); - - } else if (i == 3) { - out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs3_config, regs->cs[i].config); - } - } - - out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); - out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); - out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); - out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); - out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); - out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); - out_be32(&ddr->sdram_data_init, regs->ddr_data_init); - out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); - out_be32(&ddr->init_addr, regs->ddr_init_addr); - out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); - - /* - * 200 painful micro-seconds must elapse between - * the DDR clock setup and the DDR config enable. - */ - udelay(200); - asm volatile("sync;isync"); - - out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); - - /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ - while (in_be32(&ddr->sdram_cfg_2) & 0x10) { - udelay(10000); /* throttle polling rate */ - } -} diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c deleted file mode 100644 index 1be51d3307..0000000000 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) -#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL -#endif - - -/* - * regs has the to-be-set values for DDR controller registers - * ctrl_num is the DDR controller number - * step: 0 goes through the initialization in one pass - * 1 sets registers and returns before enabling controller - * 2 resumes from step 1 and continues to initialize - * Dividing the initialization to two steps to deassert DDR reset signal - * to comply with JEDEC specs for RDIMMs. - */ -void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step) -{ - unsigned int i, bus_width; - volatile ccsr_ddr_t *ddr; - u32 temp_sdram_cfg; - u32 total_gb_size_per_controller; - int timeout; -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 - int timeout_save; - volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR; - unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t; - int csn = -1; -#endif - - switch (ctrl_num) { - case 0: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; - break; -#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) - case 1: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR; - break; -#endif -#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) - case 2: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR; - break; -#endif -#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) - case 3: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR; - break; -#endif - default: - printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); - return; - } - - if (step == 2) - goto step2; - - if (regs->ddr_eor) - out_be32(&ddr->eor, regs->ddr_eor); -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 - debug("Workaround for ERRATUM_DDR111_DDR134\n"); - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; - cs_ea = regs->cs[i].bnds & 0xfff; - if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) { - csn = i; - csn_bnds_backup = regs->cs[i].bnds; - csn_bnds_t = (unsigned int *) ®s->cs[i].bnds; - if (cs_ea > 0xeff) - *csn_bnds_t = regs->cs[i].bnds + 0x01000000; - else - *csn_bnds_t = regs->cs[i].bnds + 0x01000100; - debug("Found cs%d_bns (0x%08x) covering 0xff000000, " - "change it to 0x%x\n", - csn, csn_bnds_backup, regs->cs[i].bnds); - break; - } - } -#endif - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (i == 0) { - out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs0_config, regs->cs[i].config); - out_be32(&ddr->cs0_config_2, regs->cs[i].config_2); - - } else if (i == 1) { - out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs1_config, regs->cs[i].config); - out_be32(&ddr->cs1_config_2, regs->cs[i].config_2); - - } else if (i == 2) { - out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs2_config, regs->cs[i].config); - out_be32(&ddr->cs2_config_2, regs->cs[i].config_2); - - } else if (i == 3) { - out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs3_config, regs->cs[i].config); - out_be32(&ddr->cs3_config_2, regs->cs[i].config_2); - } - } - - out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); - out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); - out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); - out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); - out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); - out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3); - out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4); - out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5); - out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6); - out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7); - out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8); - out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); - out_be32(&ddr->sdram_data_init, regs->ddr_data_init); - out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); - out_be32(&ddr->init_addr, regs->ddr_init_addr); - out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); - - out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4); - out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5); - out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); - out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); -#ifndef CONFIG_SYS_FSL_DDR_EMU - /* - * Skip these two registers if running on emulator - * because emulator doesn't have skew between bytes. - */ - - if (regs->ddr_wrlvl_cntl_2) - out_be32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2); - if (regs->ddr_wrlvl_cntl_3) - out_be32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3); -#endif - - out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); - out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); - out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); - out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1); - out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); - out_be32(&ddr->err_disable, regs->err_disable); - out_be32(&ddr->err_int_en, regs->err_int_en); - for (i = 0; i < 32; i++) { - if (regs->debug[i]) { - debug("Write to debug_%d as %08x\n", i+1, regs->debug[i]); - out_be32(&ddr->debug[i], regs->debug[i]); - } - } -#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934 - out_be32(&ddr->debug[28], 0x30003000); -#endif - -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474 - out_be32(&ddr->debug[12], 0x00000015); - out_be32(&ddr->debug[21], 0x24000000); -#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */ - - /* - * For RDIMMs, JEDEC spec requires clocks to be stable before reset is - * deasserted. Clocks start when any chip select is enabled and clock - * control register is set. Because all DDR components are connected to - * one reset signal, this needs to be done in two steps. Step 1 is to - * get the clocks started. Step 2 resumes after reset signal is - * deasserted. - */ - if (step == 1) { - udelay(200); - return; - } - -step2: - /* Set, but do not enable the memory */ - temp_sdram_cfg = regs->ddr_sdram_cfg; - temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); - out_be32(&ddr->sdram_cfg, temp_sdram_cfg); -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003 - debug("Workaround for ERRATUM_DDR_A003\n"); - if (regs->ddr_sdram_rcw_2 & 0x00f00000) { - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); - out_be32(&ddr->debug[2], 0x00000400); - out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff); - out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff); - out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb); - out_be32(&ddr->mtcr, 0); - out_be32(&ddr->debug[12], 0x00000015); - out_be32(&ddr->debug[21], 0x24000000); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff); - out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN); - - asm volatile("sync;isync"); - while (!(in_be32(&ddr->debug[1]) & 0x2)) - ; - - switch (regs->ddr_sdram_rcw_2 & 0x00f00000) { - case 0x00000000: - out_be32(&ddr->sdram_md_cntl, - MD_CNTL_MD_EN | - MD_CNTL_CS_SEL_CS0_CS1 | - 0x04000000 | - MD_CNTL_WRCW | - MD_CNTL_MD_VALUE(0x02)); - break; - case 0x00100000: - out_be32(&ddr->sdram_md_cntl, - MD_CNTL_MD_EN | - MD_CNTL_CS_SEL_CS0_CS1 | - 0x04000000 | - MD_CNTL_WRCW | - MD_CNTL_MD_VALUE(0x0a)); - break; - case 0x00200000: - out_be32(&ddr->sdram_md_cntl, - MD_CNTL_MD_EN | - MD_CNTL_CS_SEL_CS0_CS1 | - 0x04000000 | - MD_CNTL_WRCW | - MD_CNTL_MD_VALUE(0x12)); - break; - case 0x00300000: - out_be32(&ddr->sdram_md_cntl, - MD_CNTL_MD_EN | - MD_CNTL_CS_SEL_CS0_CS1 | - 0x04000000 | - MD_CNTL_WRCW | - MD_CNTL_MD_VALUE(0x1a)); - break; - default: - out_be32(&ddr->sdram_md_cntl, - MD_CNTL_MD_EN | - MD_CNTL_CS_SEL_CS0_CS1 | - 0x04000000 | - MD_CNTL_WRCW | - MD_CNTL_MD_VALUE(0x02)); - printf("Unsupported RC10\n"); - break; - } - - while (in_be32(&ddr->sdram_md_cntl) & 0x80000000) - ; - udelay(6); - out_be32(&ddr->sdram_cfg, temp_sdram_cfg); - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); - out_be32(&ddr->debug[2], 0x0); - out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); - out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); - out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - out_be32(&ddr->debug[12], 0x0); - out_be32(&ddr->debug[21], 0x0); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); - - } -#endif - /* - * For 8572 DDR1 erratum - DDR controller may enter illegal state - * when operatiing in 32-bit bus mode with 4-beat bursts, - * This erratum does not affect DDR3 mode, only for DDR2 mode. - */ -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115 - debug("Workaround for ERRATUM_DDR_115\n"); - if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2) - && in_be32(&ddr->sdram_cfg) & 0x80000) { - /* set DEBUG_1[31] */ - setbits_be32(&ddr->debug[0], 1); - } -#endif -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 - debug("Workaround for ERRATUM_DDR111_DDR134\n"); - /* - * This is the combined workaround for DDR111 and DDR134 - * following the published errata for MPC8572 - */ - - /* 1. Set EEBACR[3] */ - setbits_be32(&ecm->eebacr, 0x10000000); - debug("Setting EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); - - /* 2. Set DINIT in SDRAM_CFG_2*/ - setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_D_INIT); - debug("Setting sdram_cfg_2[D_INIT] to 0x%08x\n", - in_be32(&ddr->sdram_cfg_2)); - - /* 3. Set DEBUG_3[21] */ - setbits_be32(&ddr->debug[2], 0x400); - debug("Setting DEBUG_3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); - -#endif /* part 1 of the workaound */ - - /* - * 500 painful micro-seconds must elapse between - * the DDR clock setup and the DDR config enable. - * DDR2 need 200 us, and DDR3 need 500 us from spec, - * we choose the max, that is 500 us for all of case. - */ - udelay(500); - asm volatile("sync;isync"); - - /* Let the controller go */ - temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI; - out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); - asm volatile("sync;isync"); - - total_gb_size_per_controller = 0; - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (!(regs->cs[i].config & 0x80000000)) - continue; - total_gb_size_per_controller += 1 << ( - ((regs->cs[i].config >> 14) & 0x3) + 2 + - ((regs->cs[i].config >> 8) & 0x7) + 12 + - ((regs->cs[i].config >> 0) & 0x7) + 8 + - 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) - - 26); /* minus 26 (count of 64M) */ - } - if (fsl_ddr_get_intl3r() & 0x80000000) /* 3-way interleaving */ - total_gb_size_per_controller *= 3; - else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */ - total_gb_size_per_controller <<= 1; - /* - * total memory / bus width = transactions needed - * transactions needed / data rate = seconds - * to add plenty of buffer, double the time - * For example, 2GB on 666MT/s 64-bit bus takes about 402ms - * Let's wait for 800ms - */ - bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) - >> SDRAM_CFG_DBW_SHIFT); - timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / - (get_ddr_freq(0) >> 20)) << 1; -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 - timeout_save = timeout; -#endif - total_gb_size_per_controller >>= 4; /* shift down to gb size */ - debug("total %d GB\n", total_gb_size_per_controller); - debug("Need to wait up to %d * 10ms\n", timeout); - - /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ - while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) && - (timeout >= 0)) { - udelay(10000); /* throttle polling rate */ - timeout--; - } - - if (timeout <= 0) - printf("Waiting for D_INIT timeout. Memory may not work.\n"); - -#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 - /* continue this workaround */ - - /* 4. Clear DEBUG3[21] */ - clrbits_be32(&ddr->debug[2], 0x400); - debug("Clearing D3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); - - /* DDR134 workaround starts */ - /* A: Clear sdram_cfg_2[odt_cfg] */ - clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_ODT_CFG_MASK); - debug("Clearing SDRAM_CFG2[ODT_CFG] to 0x%08x\n", - in_be32(&ddr->sdram_cfg_2)); - - /* B: Set DEBUG1[15] */ - setbits_be32(&ddr->debug[0], 0x10000); - debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); - - /* C: Set timing_cfg_2[cpo] to 0b11111 */ - setbits_be32(&ddr->timing_cfg_2, TIMING_CFG_2_CPO_MASK); - debug("Setting TMING_CFG_2[CPO] to 0x%08x\n", - in_be32(&ddr->timing_cfg_2)); - - /* D: Set D6 to 0x9f9f9f9f */ - out_be32(&ddr->debug[5], 0x9f9f9f9f); - debug("Setting D6 to 0x%08x\n", in_be32(&ddr->debug[5])); - - /* E: Set D7 to 0x9f9f9f9f */ - out_be32(&ddr->debug[6], 0x9f9f9f9f); - debug("Setting D7 to 0x%08x\n", in_be32(&ddr->debug[6])); - - /* F: Set D2[20] */ - setbits_be32(&ddr->debug[1], 0x800); - debug("Setting D2[20] to 0x%08x\n", in_be32(&ddr->debug[1])); - - /* G: Poll on D2[20] until cleared */ - while (in_be32(&ddr->debug[1]) & 0x800) - udelay(10000); /* throttle polling rate */ - - /* H: Clear D1[15] */ - clrbits_be32(&ddr->debug[0], 0x10000); - debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); - - /* I: Set sdram_cfg_2[odt_cfg] */ - setbits_be32(&ddr->sdram_cfg_2, - regs->ddr_sdram_cfg_2 & SDRAM_CFG2_ODT_CFG_MASK); - debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); - - /* Continuing with the DDR111 workaround */ - /* 5. Set D2[21] */ - setbits_be32(&ddr->debug[1], 0x400); - debug("Setting D2[21] to 0x%08x\n", in_be32(&ddr->debug[1])); - - /* 6. Poll D2[21] until its cleared */ - while (in_be32(&ddr->debug[1]) & 0x400) - udelay(10000); /* throttle polling rate */ - - /* 7. Wait for state machine 2nd run, roughly 400ms/GB */ - debug("Wait for %d * 10ms\n", timeout_save); - udelay(timeout_save * 10000); - - /* 8. Set sdram_cfg_2[dinit] if options requires */ - setbits_be32(&ddr->sdram_cfg_2, - regs->ddr_sdram_cfg_2 & SDRAM_CFG2_D_INIT); - debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); - - /* 9. Poll until dinit is cleared */ - timeout = timeout_save; - debug("Need to wait up to %d * 10ms\n", timeout); - while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) && - (timeout >= 0)) { - udelay(10000); /* throttle polling rate */ - timeout--; - } - - if (timeout <= 0) - printf("Waiting for D_INIT timeout. Memory may not work.\n"); - - /* 10. Clear EEBACR[3] */ - clrbits_be32(&ecm->eebacr, 10000000); - debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); - - if (csn != -1) { - csn_bnds_t = (unsigned int *) ®s->cs[csn].bnds; - *csn_bnds_t = csn_bnds_backup; - debug("Change cs%d_bnds back to 0x%08x\n", - csn, regs->cs[csn].bnds); - setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */ - switch (csn) { - case 0: - out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds); - break; - case 1: - out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); - break; - case 2: - out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); - break; - case 3: - out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); - break; - } - clrbits_be32(&ddr->sdram_cfg, 0x2); - } -#endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */ -} diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c index 5f198eb305..88c8e65930 100644 --- a/arch/powerpc/cpu/mpc85xx/mp.c +++ b/arch/powerpc/cpu/mpc85xx/mp.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "mp.h" DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/powerpc/cpu/mpc86xx/Makefile b/arch/powerpc/cpu/mpc86xx/Makefile index bcb786dcab..0f790b0efc 100644 --- a/arch/powerpc/cpu/mpc86xx/Makefile +++ b/arch/powerpc/cpu/mpc86xx/Makefile @@ -16,9 +16,6 @@ obj-$(CONFIG_MP) += release.o obj-y += cpu.o obj-y += cpu_init.o -# 8610 & 8641 are identical w/regards to DDR -obj-$(CONFIG_MPC8610) += ddr-8641.o -obj-$(CONFIG_MPC8641) += ddr-8641.o obj-$(CONFIG_OF_LIBFDT) += fdt.o obj-y += interrupts.o obj-$(CONFIG_MP) += mp.o diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c deleted file mode 100644 index 33a91f9f78..0000000000 --- a/arch/powerpc/cpu/mpc86xx/ddr-8641.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include - -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) -#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL -#endif - -void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step) -{ - unsigned int i; - volatile ccsr_ddr_t *ddr; - - switch (ctrl_num) { - case 0: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; - break; - case 1: - ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR; - break; - default: - printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); - return; - } - - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (i == 0) { - out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs0_config, regs->cs[i].config); - - } else if (i == 1) { - out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs1_config, regs->cs[i].config); - - } else if (i == 2) { - out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs2_config, regs->cs[i].config); - - } else if (i == 3) { - out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); - out_be32(&ddr->cs3_config, regs->cs[i].config); - } - } - - out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); - out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); - out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); - out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); - out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); - out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); - out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); - out_be32(&ddr->sdram_mode_cntl, regs->ddr_sdram_md_cntl); - out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); - out_be32(&ddr->sdram_data_init, regs->ddr_data_init); - out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); - out_be32(&ddr->init_addr, regs->ddr_init_addr); - out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); - - debug("before go\n"); - - /* - * 200 painful micro-seconds must elapse between - * the DDR clock setup and the DDR config enable. - */ - udelay(200); - asm volatile("sync;isync"); - - out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); - - /* - * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done - */ - while (in_be32(&ddr->sdram_cfg_2) & 0x10) { - udelay(10000); /* throttle polling rate */ - } -} diff --git a/arch/powerpc/cpu/mpc8xxx/Makefile b/arch/powerpc/cpu/mpc8xxx/Makefile index 1d083bf354..395fed16b6 100644 --- a/arch/powerpc/cpu/mpc8xxx/Makefile +++ b/arch/powerpc/cpu/mpc8xxx/Makefile @@ -31,9 +31,3 @@ obj-$(CONFIG_SYS_SRIO) += srio.o obj-$(CONFIG_FSL_LAW) += law.o endif - -ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/ -else -obj-y += ddr/ -endif diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile deleted file mode 100644 index 8cbc06c95a..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2008-2011 Freescale Semiconductor, Inc. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# Version 2 as published by the Free Software Foundation. -# - -obj-$(CONFIG_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \ - lc_common_dimm_params.o - -obj-$(CONFIG_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \ - lc_common_dimm_params.o - -obj-$(CONFIG_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \ - lc_common_dimm_params.o -ifdef CONFIG_DDR_SPD -SPD := y -endif -ifdef CONFIG_SPD_EEPROM -SPD := y -endif -ifdef SPD -obj-$(CONFIG_FSL_DDR1) += ddr1_dimm_params.o -obj-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o -obj-$(CONFIG_FSL_DDR3) += ddr3_dimm_params.o -endif - -obj-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h deleted file mode 100644 index 76338d4e6c..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#ifndef COMMON_TIMING_PARAMS_H -#define COMMON_TIMING_PARAMS_H - -typedef struct { - /* parameters to constrict */ - - unsigned int tckmin_x_ps; - unsigned int tckmax_ps; - unsigned int tckmax_max_ps; - unsigned int trcd_ps; - unsigned int trp_ps; - unsigned int tras_ps; - - unsigned int twr_ps; /* maximum = 63750 ps */ - unsigned int twtr_ps; /* maximum = 63750 ps */ - unsigned int trfc_ps; /* maximum = 255 ns + 256 ns + .75 ns - = 511750 ps */ - - unsigned int trrd_ps; /* maximum = 63750 ps */ - unsigned int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ - - unsigned int refresh_rate_ps; - unsigned int extended_op_srt; - - unsigned int tis_ps; /* byte 32, spd->ca_setup */ - unsigned int tih_ps; /* byte 33, spd->ca_hold */ - unsigned int tds_ps; /* byte 34, spd->data_setup */ - unsigned int tdh_ps; /* byte 35, spd->data_hold */ - unsigned int trtp_ps; /* byte 38, spd->trtp */ - unsigned int tdqsq_max_ps; /* byte 44, spd->tdqsq */ - unsigned int tqhs_ps; /* byte 45, spd->tqhs */ - - unsigned int ndimms_present; - unsigned int lowest_common_SPD_caslat; - unsigned int highest_common_derated_caslat; - unsigned int additive_latency; - unsigned int all_dimms_burst_lengths_bitmask; - unsigned int all_dimms_registered; - unsigned int all_dimms_unbuffered; - unsigned int all_dimms_ecc_capable; - - unsigned long long total_mem; - unsigned long long base_address; - - /* DDR3 RDIMM */ - unsigned char rcw[16]; /* Register Control Word 0-15 */ -} common_timing_params_t; - -#endif diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c deleted file mode 100644 index dcfc48aa95..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ /dev/null @@ -1,1656 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. - * Based on code from spd_sdram.c - * Author: James Yang [at freescale.com] - */ - -#include -#include - -#include "ddr.h" - -#define _DDR_ADDR CONFIG_SYS_MPC8xxx_DDR_ADDR - -static u32 fsl_ddr_get_version(void) -{ - ccsr_ddr_t *ddr; - u32 ver_major_minor_errata; - - ddr = (void *)_DDR_ADDR; - ver_major_minor_errata = (in_be32(&ddr->ip_rev1) & 0xFFFF) << 8; - ver_major_minor_errata |= (in_be32(&ddr->ip_rev2) & 0xFF00) >> 8; - - return ver_major_minor_errata; -} - -unsigned int picos_to_mclk(unsigned int picos); - -/* - * Determine Rtt value. - * - * This should likely be either board or controller specific. - * - * Rtt(nominal) - DDR2: - * 0 = Rtt disabled - * 1 = 75 ohm - * 2 = 150 ohm - * 3 = 50 ohm - * Rtt(nominal) - DDR3: - * 0 = Rtt disabled - * 1 = 60 ohm - * 2 = 120 ohm - * 3 = 40 ohm - * 4 = 20 ohm - * 5 = 30 ohm - * - * FIXME: Apparently 8641 needs a value of 2 - * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572 - * - * FIXME: There was some effort down this line earlier: - * - * unsigned int i; - * for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) { - * if (popts->dimmslot[i].num_valid_cs - * && (popts->cs_local_opts[2*i].odt_rd_cfg - * || popts->cs_local_opts[2*i].odt_wr_cfg)) { - * rtt = 2; - * break; - * } - * } - */ -static inline int fsl_ddr_get_rtt(void) -{ - int rtt; - -#if defined(CONFIG_FSL_DDR1) - rtt = 0; -#elif defined(CONFIG_FSL_DDR2) - rtt = 3; -#else - rtt = 0; -#endif - - return rtt; -} - -/* - * compute the CAS write latency according to DDR3 spec - * CWL = 5 if tCK >= 2.5ns - * 6 if 2.5ns > tCK >= 1.875ns - * 7 if 1.875ns > tCK >= 1.5ns - * 8 if 1.5ns > tCK >= 1.25ns - * 9 if 1.25ns > tCK >= 1.07ns - * 10 if 1.07ns > tCK >= 0.935ns - * 11 if 0.935ns > tCK >= 0.833ns - * 12 if 0.833ns > tCK >= 0.75ns - */ -static inline unsigned int compute_cas_write_latency(void) -{ - unsigned int cwl; - const unsigned int mclk_ps = get_memory_clk_period_ps(); - - if (mclk_ps >= 2500) - cwl = 5; - else if (mclk_ps >= 1875) - cwl = 6; - else if (mclk_ps >= 1500) - cwl = 7; - else if (mclk_ps >= 1250) - cwl = 8; - else if (mclk_ps >= 1070) - cwl = 9; - else if (mclk_ps >= 935) - cwl = 10; - else if (mclk_ps >= 833) - cwl = 11; - else if (mclk_ps >= 750) - cwl = 12; - else { - cwl = 12; - printf("Warning: CWL is out of range\n"); - } - return cwl; -} - -/* Chip Select Configuration (CSn_CONFIG) */ -static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const dimm_params_t *dimm_params) -{ - unsigned int cs_n_en = 0; /* Chip Select enable */ - unsigned int intlv_en = 0; /* Memory controller interleave enable */ - unsigned int intlv_ctl = 0; /* Interleaving control */ - unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */ - unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */ - unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */ - unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */ - unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */ - unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */ - int go_config = 0; - - /* Compute CS_CONFIG only for existing ranks of each DIMM. */ - switch (i) { - case 0: - if (dimm_params[dimm_number].n_ranks > 0) { - go_config = 1; - /* These fields only available in CS0_CONFIG */ - if (!popts->memctl_interleaving) - break; - switch (popts->memctl_interleaving_mode) { - case FSL_DDR_CACHE_LINE_INTERLEAVING: - case FSL_DDR_PAGE_INTERLEAVING: - case FSL_DDR_BANK_INTERLEAVING: - case FSL_DDR_SUPERBANK_INTERLEAVING: - intlv_en = popts->memctl_interleaving; - intlv_ctl = popts->memctl_interleaving_mode; - break; - default: - break; - } - } - break; - case 1: - if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \ - (dimm_number == 1 && dimm_params[1].n_ranks > 0)) - go_config = 1; - break; - case 2: - if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \ - (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0)) - go_config = 1; - break; - case 3: - if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \ - (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \ - (dimm_number == 3 && dimm_params[3].n_ranks > 0)) - go_config = 1; - break; - default: - break; - } - if (go_config) { - unsigned int n_banks_per_sdram_device; - cs_n_en = 1; - ap_n_en = popts->cs_local_opts[i].auto_precharge; - odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg; - odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg; - n_banks_per_sdram_device - = dimm_params[dimm_number].n_banks_per_sdram_device; - ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2; - row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12; - col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8; - } - ddr->cs[i].config = (0 - | ((cs_n_en & 0x1) << 31) - | ((intlv_en & 0x3) << 29) - | ((intlv_ctl & 0xf) << 24) - | ((ap_n_en & 0x1) << 23) - - /* XXX: some implementation only have 1 bit starting at left */ - | ((odt_rd_cfg & 0x7) << 20) - - /* XXX: Some implementation only have 1 bit starting at left */ - | ((odt_wr_cfg & 0x7) << 16) - - | ((ba_bits_cs_n & 0x3) << 14) - | ((row_bits_cs_n & 0x7) << 8) - | ((col_bits_cs_n & 0x7) << 0) - ); - debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config); -} - -/* Chip Select Configuration 2 (CSn_CONFIG_2) */ -/* FIXME: 8572 */ -static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int pasr_cfg = 0; /* Partial array self refresh config */ - - ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24); - debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2); -} - -/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ - -#if !defined(CONFIG_FSL_DDR1) -static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) -{ -#if CONFIG_DIMM_SLOTS_PER_CTLR == 1 - if (dimm_params[0].n_ranks == 4) - return 1; -#endif - -#if CONFIG_DIMM_SLOTS_PER_CTLR == 2 - if ((dimm_params[0].n_ranks == 2) && - (dimm_params[1].n_ranks == 2)) - return 1; - -#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - if (dimm_params[0].n_ranks == 4) - return 1; -#endif -#endif - return 0; -} - -/* - * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0) - * - * Avoid writing for DDR I. The new PQ38 DDR controller - * dreams up non-zero default values to be backwards compatible. - */ -static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const dimm_params_t *dimm_params) -{ - unsigned char trwt_mclk = 0; /* Read-to-write turnaround */ - unsigned char twrt_mclk = 0; /* Write-to-read turnaround */ - /* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */ - unsigned char trrt_mclk = 0; /* Read-to-read turnaround */ - unsigned char twwt_mclk = 0; /* Write-to-write turnaround */ - - /* Active powerdown exit timing (tXARD and tXARDS). */ - unsigned char act_pd_exit_mclk; - /* Precharge powerdown exit timing (tXP). */ - unsigned char pre_pd_exit_mclk; - /* ODT powerdown exit timing (tAXPD). */ - unsigned char taxpd_mclk; - /* Mode register set cycle time (tMRD). */ - unsigned char tmrd_mclk; - -#ifdef CONFIG_FSL_DDR3 - /* - * (tXARD and tXARDS). Empirical? - * The DDR3 spec has not tXARD, - * we use the tXP instead of it. - * tXP=max(3nCK, 7.5ns) for DDR3. - * spec has not the tAXPD, we use - * tAXPD=1, need design to confirm. - */ - int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */ - unsigned int data_rate = get_ddr_freq(0); - tmrd_mclk = 4; - /* set the turnaround time */ - - /* - * for single quad-rank DIMM and two dual-rank DIMMs - * to avoid ODT overlap - */ - if (avoid_odt_overlap(dimm_params)) { - twwt_mclk = 2; - trrt_mclk = 1; - } - /* for faster clock, need more time for data setup */ - trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1; - - if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving)) - twrt_mclk = 1; - - if (popts->dynamic_power == 0) { /* powerdown is not used */ - act_pd_exit_mclk = 1; - pre_pd_exit_mclk = 1; - taxpd_mclk = 1; - } else { - /* act_pd_exit_mclk = tXARD, see above */ - act_pd_exit_mclk = picos_to_mclk(tXP); - /* Mode register MR0[A12] is '1' - fast exit */ - pre_pd_exit_mclk = act_pd_exit_mclk; - taxpd_mclk = 1; - } -#else /* CONFIG_FSL_DDR2 */ - /* - * (tXARD and tXARDS). Empirical? - * tXARD = 2 for DDR2 - * tXP=2 - * tAXPD=8 - */ - act_pd_exit_mclk = 2; - pre_pd_exit_mclk = 2; - taxpd_mclk = 8; - tmrd_mclk = 2; -#endif - - if (popts->trwt_override) - trwt_mclk = popts->trwt; - - ddr->timing_cfg_0 = (0 - | ((trwt_mclk & 0x3) << 30) /* RWT */ - | ((twrt_mclk & 0x3) << 28) /* WRT */ - | ((trrt_mclk & 0x3) << 26) /* RRT */ - | ((twwt_mclk & 0x3) << 24) /* WWT */ - | ((act_pd_exit_mclk & 0x7) << 20) /* ACT_PD_EXIT */ - | ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */ - | ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */ - | ((tmrd_mclk & 0xf) << 0) /* MRS_CYC */ - ); - debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); -} -#endif /* defined(CONFIG_FSL_DDR2) */ - -/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ -static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency) -{ - /* Extended precharge to activate interval (tRP) */ - unsigned int ext_pretoact = 0; - /* Extended Activate to precharge interval (tRAS) */ - unsigned int ext_acttopre = 0; - /* Extended activate to read/write interval (tRCD) */ - unsigned int ext_acttorw = 0; - /* Extended refresh recovery time (tRFC) */ - unsigned int ext_refrec; - /* Extended MCAS latency from READ cmd */ - unsigned int ext_caslat = 0; - /* Extended last data to precharge interval (tWR) */ - unsigned int ext_wrrec = 0; - /* Control Adjust */ - unsigned int cntl_adj = 0; - - ext_pretoact = picos_to_mclk(common_dimm->trp_ps) >> 4; - ext_acttopre = picos_to_mclk(common_dimm->tras_ps) >> 4; - ext_acttorw = picos_to_mclk(common_dimm->trcd_ps) >> 4; - ext_caslat = (2 * cas_latency - 1) >> 4; - ext_refrec = (picos_to_mclk(common_dimm->trfc_ps) - 8) >> 4; - /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ - ext_wrrec = (picos_to_mclk(common_dimm->twr_ps) + - (popts->otf_burst_chop_en ? 2 : 0)) >> 4; - - ddr->timing_cfg_3 = (0 - | ((ext_pretoact & 0x1) << 28) - | ((ext_acttopre & 0x3) << 24) - | ((ext_acttorw & 0x1) << 22) - | ((ext_refrec & 0x1F) << 16) - | ((ext_caslat & 0x3) << 12) - | ((ext_wrrec & 0x1) << 8) - | ((cntl_adj & 0x7) << 0) - ); - debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3); -} - -/* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */ -static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency) -{ - /* Precharge-to-activate interval (tRP) */ - unsigned char pretoact_mclk; - /* Activate to precharge interval (tRAS) */ - unsigned char acttopre_mclk; - /* Activate to read/write interval (tRCD) */ - unsigned char acttorw_mclk; - /* CASLAT */ - unsigned char caslat_ctrl; - /* Refresh recovery time (tRFC) ; trfc_low */ - unsigned char refrec_ctrl; - /* Last data to precharge minimum interval (tWR) */ - unsigned char wrrec_mclk; - /* Activate-to-activate interval (tRRD) */ - unsigned char acttoact_mclk; - /* Last write data pair to read command issue interval (tWTR) */ - unsigned char wrtord_mclk; - /* DDR_SDRAM_MODE doesn't support 9,11,13,15 */ - static const u8 wrrec_table[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0}; - - pretoact_mclk = picos_to_mclk(common_dimm->trp_ps); - acttopre_mclk = picos_to_mclk(common_dimm->tras_ps); - acttorw_mclk = picos_to_mclk(common_dimm->trcd_ps); - - /* - * Translate CAS Latency to a DDR controller field value: - * - * CAS Lat DDR I DDR II Ctrl - * Clocks SPD Bit SPD Bit Value - * ------- ------- ------- ----- - * 1.0 0 0001 - * 1.5 1 0010 - * 2.0 2 2 0011 - * 2.5 3 0100 - * 3.0 4 3 0101 - * 3.5 5 0110 - * 4.0 4 0111 - * 4.5 1000 - * 5.0 5 1001 - */ -#if defined(CONFIG_FSL_DDR1) - caslat_ctrl = (cas_latency + 1) & 0x07; -#elif defined(CONFIG_FSL_DDR2) - caslat_ctrl = 2 * cas_latency - 1; -#else - /* - * if the CAS latency more than 8 cycle, - * we need set extend bit for it at - * TIMING_CFG_3[EXT_CASLAT] - */ - caslat_ctrl = 2 * cas_latency - 1; -#endif - - refrec_ctrl = picos_to_mclk(common_dimm->trfc_ps) - 8; - wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); - - if (wrrec_mclk > 16) - printf("Error: WRREC doesn't support more than 16 clocks\n"); - else - wrrec_mclk = wrrec_table[wrrec_mclk - 1]; - if (popts->otf_burst_chop_en) - wrrec_mclk += 2; - - acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps); - /* - * JEDEC has min requirement for tRRD - */ -#if defined(CONFIG_FSL_DDR3) - if (acttoact_mclk < 4) - acttoact_mclk = 4; -#endif - wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps); - /* - * JEDEC has some min requirements for tWTR - */ -#if defined(CONFIG_FSL_DDR2) - if (wrtord_mclk < 2) - wrtord_mclk = 2; -#elif defined(CONFIG_FSL_DDR3) - if (wrtord_mclk < 4) - wrtord_mclk = 4; -#endif - if (popts->otf_burst_chop_en) - wrtord_mclk += 2; - - ddr->timing_cfg_1 = (0 - | ((pretoact_mclk & 0x0F) << 28) - | ((acttopre_mclk & 0x0F) << 24) - | ((acttorw_mclk & 0xF) << 20) - | ((caslat_ctrl & 0xF) << 16) - | ((refrec_ctrl & 0xF) << 12) - | ((wrrec_mclk & 0x0F) << 8) - | ((acttoact_mclk & 0x0F) << 4) - | ((wrtord_mclk & 0x0F) << 0) - ); - debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); -} - -/* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */ -static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency, - unsigned int additive_latency) -{ - /* Additive latency */ - unsigned char add_lat_mclk; - /* CAS-to-preamble override */ - unsigned short cpo; - /* Write latency */ - unsigned char wr_lat; - /* Read to precharge (tRTP) */ - unsigned char rd_to_pre; - /* Write command to write data strobe timing adjustment */ - unsigned char wr_data_delay; - /* Minimum CKE pulse width (tCKE) */ - unsigned char cke_pls; - /* Window for four activates (tFAW) */ - unsigned short four_act; - - /* FIXME add check that this must be less than acttorw_mclk */ - add_lat_mclk = additive_latency; - cpo = popts->cpo_override; - -#if defined(CONFIG_FSL_DDR1) - /* - * This is a lie. It should really be 1, but if it is - * set to 1, bits overlap into the old controller's - * otherwise unused ACSM field. If we leave it 0, then - * the HW will magically treat it as 1 for DDR 1. Oh Yea. - */ - wr_lat = 0; -#elif defined(CONFIG_FSL_DDR2) - wr_lat = cas_latency - 1; -#else - wr_lat = compute_cas_write_latency(); -#endif - - rd_to_pre = picos_to_mclk(common_dimm->trtp_ps); - /* - * JEDEC has some min requirements for tRTP - */ -#if defined(CONFIG_FSL_DDR2) - if (rd_to_pre < 2) - rd_to_pre = 2; -#elif defined(CONFIG_FSL_DDR3) - if (rd_to_pre < 4) - rd_to_pre = 4; -#endif - if (additive_latency) - rd_to_pre += additive_latency; - if (popts->otf_burst_chop_en) - rd_to_pre += 2; /* according to UM */ - - wr_data_delay = popts->write_data_delay; - cke_pls = picos_to_mclk(popts->tcke_clock_pulse_width_ps); - four_act = picos_to_mclk(popts->tfaw_window_four_activates_ps); - - ddr->timing_cfg_2 = (0 - | ((add_lat_mclk & 0xf) << 28) - | ((cpo & 0x1f) << 23) - | ((wr_lat & 0xf) << 19) - | ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT) - | ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT) - | ((cke_pls & 0x7) << 6) - | ((four_act & 0x3f) << 0) - ); - debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); -} - -/* DDR SDRAM Register Control Word */ -static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm) -{ - if (common_dimm->all_dimms_registered && - !common_dimm->all_dimms_unbuffered) { - if (popts->rcw_override) { - ddr->ddr_sdram_rcw_1 = popts->rcw_1; - ddr->ddr_sdram_rcw_2 = popts->rcw_2; - } else { - ddr->ddr_sdram_rcw_1 = - common_dimm->rcw[0] << 28 | \ - common_dimm->rcw[1] << 24 | \ - common_dimm->rcw[2] << 20 | \ - common_dimm->rcw[3] << 16 | \ - common_dimm->rcw[4] << 12 | \ - common_dimm->rcw[5] << 8 | \ - common_dimm->rcw[6] << 4 | \ - common_dimm->rcw[7]; - ddr->ddr_sdram_rcw_2 = - common_dimm->rcw[8] << 28 | \ - common_dimm->rcw[9] << 24 | \ - common_dimm->rcw[10] << 20 | \ - common_dimm->rcw[11] << 16 | \ - common_dimm->rcw[12] << 12 | \ - common_dimm->rcw[13] << 8 | \ - common_dimm->rcw[14] << 4 | \ - common_dimm->rcw[15]; - } - debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1); - debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2); - } -} - -/* DDR SDRAM control configuration (DDR_SDRAM_CFG) */ -static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm) -{ - unsigned int mem_en; /* DDR SDRAM interface logic enable */ - unsigned int sren; /* Self refresh enable (during sleep) */ - unsigned int ecc_en; /* ECC enable. */ - unsigned int rd_en; /* Registered DIMM enable */ - unsigned int sdram_type; /* Type of SDRAM */ - unsigned int dyn_pwr; /* Dynamic power management mode */ - unsigned int dbw; /* DRAM dta bus width */ - unsigned int eight_be = 0; /* 8-beat burst enable, DDR2 is zero */ - unsigned int ncap = 0; /* Non-concurrent auto-precharge */ - unsigned int threet_en; /* Enable 3T timing */ - unsigned int twot_en; /* Enable 2T timing */ - unsigned int ba_intlv_ctl; /* Bank (CS) interleaving control */ - unsigned int x32_en = 0; /* x32 enable */ - unsigned int pchb8 = 0; /* precharge bit 8 enable */ - unsigned int hse; /* Global half strength override */ - unsigned int mem_halt = 0; /* memory controller halt */ - unsigned int bi = 0; /* Bypass initialization */ - - mem_en = 1; - sren = popts->self_refresh_in_sleep; - if (common_dimm->all_dimms_ecc_capable) { - /* Allow setting of ECC only if all DIMMs are ECC. */ - ecc_en = popts->ecc_mode; - } else { - ecc_en = 0; - } - - if (common_dimm->all_dimms_registered && - !common_dimm->all_dimms_unbuffered) { - rd_en = 1; - twot_en = 0; - } else { - rd_en = 0; - twot_en = popts->twot_en; - } - - sdram_type = CONFIG_FSL_SDRAM_TYPE; - - dyn_pwr = popts->dynamic_power; - dbw = popts->data_bus_width; - /* 8-beat burst enable DDR-III case - * we must clear it when use the on-the-fly mode, - * must set it when use the 32-bits bus mode. - */ - if (sdram_type == SDRAM_TYPE_DDR3) { - if (popts->burst_length == DDR_BL8) - eight_be = 1; - if (popts->burst_length == DDR_OTF) - eight_be = 0; - if (dbw == 0x1) - eight_be = 1; - } - - threet_en = popts->threet_en; - ba_intlv_ctl = popts->ba_intlv_ctl; - hse = popts->half_strength_driver_enable; - - ddr->ddr_sdram_cfg = (0 - | ((mem_en & 0x1) << 31) - | ((sren & 0x1) << 30) - | ((ecc_en & 0x1) << 29) - | ((rd_en & 0x1) << 28) - | ((sdram_type & 0x7) << 24) - | ((dyn_pwr & 0x1) << 21) - | ((dbw & 0x3) << 19) - | ((eight_be & 0x1) << 18) - | ((ncap & 0x1) << 17) - | ((threet_en & 0x1) << 16) - | ((twot_en & 0x1) << 15) - | ((ba_intlv_ctl & 0x7F) << 8) - | ((x32_en & 0x1) << 5) - | ((pchb8 & 0x1) << 4) - | ((hse & 0x1) << 3) - | ((mem_halt & 0x1) << 1) - | ((bi & 0x1) << 0) - ); - debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg); -} - -/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */ -static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const unsigned int unq_mrs_en) -{ - unsigned int frc_sr = 0; /* Force self refresh */ - unsigned int sr_ie = 0; /* Self-refresh interrupt enable */ - unsigned int dll_rst_dis; /* DLL reset disable */ - unsigned int dqs_cfg; /* DQS configuration */ - unsigned int odt_cfg = 0; /* ODT configuration */ - unsigned int num_pr; /* Number of posted refreshes */ - unsigned int slow = 0; /* DDR will be run less than 1250 */ - unsigned int x4_en = 0; /* x4 DRAM enable */ - unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */ - unsigned int ap_en; /* Address Parity Enable */ - unsigned int d_init; /* DRAM data initialization */ - unsigned int rcw_en = 0; /* Register Control Word Enable */ - unsigned int md_en = 0; /* Mirrored DIMM Enable */ - unsigned int qd_en = 0; /* quad-rank DIMM Enable */ - int i; - - dll_rst_dis = 1; /* Make this configurable */ - dqs_cfg = popts->dqs_config; - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (popts->cs_local_opts[i].odt_rd_cfg - || popts->cs_local_opts[i].odt_wr_cfg) { - odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; - break; - } - } - - num_pr = 1; /* Make this configurable */ - - /* - * 8572 manual says - * {TIMING_CFG_1[PRETOACT] - * + [DDR_SDRAM_CFG_2[NUM_PR] - * * ({EXT_REFREC || REFREC} + 8 + 2)]} - * << DDR_SDRAM_INTERVAL[REFINT] - */ -#if defined(CONFIG_FSL_DDR3) - obc_cfg = popts->otf_burst_chop_en; -#else - obc_cfg = 0; -#endif - -#if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7) - slow = get_ddr_freq(0) < 1249000000; -#endif - - if (popts->registered_dimm_en) { - rcw_en = 1; - ap_en = popts->ap_en; - } else { - ap_en = 0; - } - - x4_en = popts->x4_en ? 1 : 0; - -#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) - /* Use the DDR controller to auto initialize memory. */ - d_init = popts->ecc_init_using_memctl; - ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE; - debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init); -#else - /* Memory will be initialized via DMA, or not at all. */ - d_init = 0; -#endif - -#if defined(CONFIG_FSL_DDR3) - md_en = popts->mirrored_dimm; -#endif - qd_en = popts->quad_rank_present ? 1 : 0; - ddr->ddr_sdram_cfg_2 = (0 - | ((frc_sr & 0x1) << 31) - | ((sr_ie & 0x1) << 30) - | ((dll_rst_dis & 0x1) << 29) - | ((dqs_cfg & 0x3) << 26) - | ((odt_cfg & 0x3) << 21) - | ((num_pr & 0xf) << 12) - | ((slow & 1) << 11) - | (x4_en << 10) - | (qd_en << 9) - | (unq_mrs_en << 8) - | ((obc_cfg & 0x1) << 6) - | ((ap_en & 0x1) << 5) - | ((d_init & 0x1) << 4) - | ((rcw_en & 0x1) << 2) - | ((md_en & 0x1) << 0) - ); - debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2); -} - -/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ -static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - const unsigned int unq_mrs_en) -{ - unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */ - unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */ - -#if defined(CONFIG_FSL_DDR3) - int i; - unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */ - unsigned int srt = 0; /* self-refresh temerature, normal range */ - unsigned int asr = 0; /* auto self-refresh disable */ - unsigned int cwl = compute_cas_write_latency() - 5; - unsigned int pasr = 0; /* partial array self refresh disable */ - - if (popts->rtt_override) - rtt_wr = popts->rtt_wr_override_value; - else - rtt_wr = popts->cs_local_opts[0].odt_rtt_wr; - - if (common_dimm->extended_op_srt) - srt = common_dimm->extended_op_srt; - - esdmode2 = (0 - | ((rtt_wr & 0x3) << 9) - | ((srt & 0x1) << 7) - | ((asr & 0x1) << 6) - | ((cwl & 0x7) << 3) - | ((pasr & 0x7) << 0)); -#endif - ddr->ddr_sdram_mode_2 = (0 - | ((esdmode2 & 0xFFFF) << 16) - | ((esdmode3 & 0xFFFF) << 0) - ); - debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2); - -#ifdef CONFIG_FSL_DDR3 - if (unq_mrs_en) { /* unique mode registers are supported */ - for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (popts->rtt_override) - rtt_wr = popts->rtt_wr_override_value; - else - rtt_wr = popts->cs_local_opts[i].odt_rtt_wr; - - esdmode2 &= 0xF9FF; /* clear bit 10, 9 */ - esdmode2 |= (rtt_wr & 0x3) << 9; - switch (i) { - case 1: - ddr->ddr_sdram_mode_4 = (0 - | ((esdmode2 & 0xFFFF) << 16) - | ((esdmode3 & 0xFFFF) << 0) - ); - break; - case 2: - ddr->ddr_sdram_mode_6 = (0 - | ((esdmode2 & 0xFFFF) << 16) - | ((esdmode3 & 0xFFFF) << 0) - ); - break; - case 3: - ddr->ddr_sdram_mode_8 = (0 - | ((esdmode2 & 0xFFFF) << 16) - | ((esdmode3 & 0xFFFF) << 0) - ); - break; - } - } - debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n", - ddr->ddr_sdram_mode_4); - debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n", - ddr->ddr_sdram_mode_6); - debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n", - ddr->ddr_sdram_mode_8); - } -#endif -} - -/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */ -static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm) -{ - unsigned int refint; /* Refresh interval */ - unsigned int bstopre; /* Precharge interval */ - - refint = picos_to_mclk(common_dimm->refresh_rate_ps); - - bstopre = popts->bstopre; - - /* refint field used 0x3FFF in earlier controllers */ - ddr->ddr_sdram_interval = (0 - | ((refint & 0xFFFF) << 16) - | ((bstopre & 0x3FFF) << 0) - ); - debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval); -} - -#if defined(CONFIG_FSL_DDR3) -/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ -static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency, - unsigned int additive_latency, - const unsigned int unq_mrs_en) -{ - unsigned short esdmode; /* Extended SDRAM mode */ - unsigned short sdmode; /* SDRAM mode */ - - /* Mode Register - MR1 */ - unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */ - unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */ - unsigned int rtt; - unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */ - unsigned int al = 0; /* Posted CAS# additive latency (AL) */ - unsigned int dic = 0; /* Output driver impedance, 40ohm */ - unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), - 1=Disable (Test/Debug) */ - - /* Mode Register - MR0 */ - unsigned int dll_on; /* DLL control for precharge PD, 0=off, 1=on */ - unsigned int wr = 0; /* Write Recovery */ - unsigned int dll_rst; /* DLL Reset */ - unsigned int mode; /* Normal=0 or Test=1 */ - unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ - /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ - unsigned int bt; - unsigned int bl; /* BL: Burst Length */ - - unsigned int wr_mclk; - /* - * DDR_SDRAM_MODE doesn't support 9,11,13,15 - * Please refer JEDEC Standard No. 79-3E for Mode Register MR0 - * for this table - */ - static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; - - const unsigned int mclk_ps = get_memory_clk_period_ps(); - int i; - - if (popts->rtt_override) - rtt = popts->rtt_override_value; - else - rtt = popts->cs_local_opts[0].odt_rtt_norm; - - if (additive_latency == (cas_latency - 1)) - al = 1; - if (additive_latency == (cas_latency - 2)) - al = 2; - - if (popts->quad_rank_present) - dic = 1; /* output driver impedance 240/7 ohm */ - - /* - * The esdmode value will also be used for writing - * MR1 during write leveling for DDR3, although the - * bits specifically related to the write leveling - * scheme will be handled automatically by the DDR - * controller. so we set the wrlvl_en = 0 here. - */ - esdmode = (0 - | ((qoff & 0x1) << 12) - | ((tdqs_en & 0x1) << 11) - | ((rtt & 0x4) << 7) /* rtt field is split */ - | ((wrlvl_en & 0x1) << 7) - | ((rtt & 0x2) << 5) /* rtt field is split */ - | ((dic & 0x2) << 4) /* DIC field is split */ - | ((al & 0x3) << 3) - | ((rtt & 0x1) << 2) /* rtt field is split */ - | ((dic & 0x1) << 1) /* DIC field is split */ - | ((dll_en & 0x1) << 0) - ); - - /* - * DLL control for precharge PD - * 0=slow exit DLL off (tXPDLL) - * 1=fast exit DLL on (tXP) - */ - dll_on = 1; - - wr_mclk = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps; - if (wr_mclk <= 16) { - wr = wr_table[wr_mclk - 5]; - } else { - printf("Error: unsupported write recovery for mode register " - "wr_mclk = %d\n", wr_mclk); - } - - dll_rst = 0; /* dll no reset */ - mode = 0; /* normal mode */ - - /* look up table to get the cas latency bits */ - if (cas_latency >= 5 && cas_latency <= 16) { - unsigned char cas_latency_table[] = { - 0x2, /* 5 clocks */ - 0x4, /* 6 clocks */ - 0x6, /* 7 clocks */ - 0x8, /* 8 clocks */ - 0xa, /* 9 clocks */ - 0xc, /* 10 clocks */ - 0xe, /* 11 clocks */ - 0x1, /* 12 clocks */ - 0x3, /* 13 clocks */ - 0x5, /* 14 clocks */ - 0x7, /* 15 clocks */ - 0x9, /* 16 clocks */ - }; - caslat = cas_latency_table[cas_latency - 5]; - } else { - printf("Error: unsupported cas latency for mode register\n"); - } - - bt = 0; /* Nibble sequential */ - - switch (popts->burst_length) { - case DDR_BL8: - bl = 0; - break; - case DDR_OTF: - bl = 1; - break; - case DDR_BC4: - bl = 2; - break; - default: - printf("Error: invalid burst length of %u specified. " - " Defaulting to on-the-fly BC4 or BL8 beats.\n", - popts->burst_length); - bl = 1; - break; - } - - sdmode = (0 - | ((dll_on & 0x1) << 12) - | ((wr & 0x7) << 9) - | ((dll_rst & 0x1) << 8) - | ((mode & 0x1) << 7) - | (((caslat >> 1) & 0x7) << 4) - | ((bt & 0x1) << 3) - | ((caslat & 1) << 2) - | ((bl & 0x3) << 0) - ); - - ddr->ddr_sdram_mode = (0 - | ((esdmode & 0xFFFF) << 16) - | ((sdmode & 0xFFFF) << 0) - ); - - debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); - - if (unq_mrs_en) { /* unique mode registers are supported */ - for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - if (popts->rtt_override) - rtt = popts->rtt_override_value; - else - rtt = popts->cs_local_opts[i].odt_rtt_norm; - - esdmode &= 0xFDBB; /* clear bit 9,6,2 */ - esdmode |= (0 - | ((rtt & 0x4) << 7) /* rtt field is split */ - | ((rtt & 0x2) << 5) /* rtt field is split */ - | ((rtt & 0x1) << 2) /* rtt field is split */ - ); - switch (i) { - case 1: - ddr->ddr_sdram_mode_3 = (0 - | ((esdmode & 0xFFFF) << 16) - | ((sdmode & 0xFFFF) << 0) - ); - break; - case 2: - ddr->ddr_sdram_mode_5 = (0 - | ((esdmode & 0xFFFF) << 16) - | ((sdmode & 0xFFFF) << 0) - ); - break; - case 3: - ddr->ddr_sdram_mode_7 = (0 - | ((esdmode & 0xFFFF) << 16) - | ((sdmode & 0xFFFF) << 0) - ); - break; - } - } - debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n", - ddr->ddr_sdram_mode_3); - debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n", - ddr->ddr_sdram_mode_5); - debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n", - ddr->ddr_sdram_mode_5); - } -} - -#else /* !CONFIG_FSL_DDR3 */ - -/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ -static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts, - const common_timing_params_t *common_dimm, - unsigned int cas_latency, - unsigned int additive_latency, - const unsigned int unq_mrs_en) -{ - unsigned short esdmode; /* Extended SDRAM mode */ - unsigned short sdmode; /* SDRAM mode */ - - /* - * FIXME: This ought to be pre-calculated in a - * technology-specific routine, - * e.g. compute_DDR2_mode_register(), and then the - * sdmode and esdmode passed in as part of common_dimm. - */ - - /* Extended Mode Register */ - unsigned int mrs = 0; /* Mode Register Set */ - unsigned int outputs = 0; /* 0=Enabled, 1=Disabled */ - unsigned int rdqs_en = 0; /* RDQS Enable: 0=no, 1=yes */ - unsigned int dqs_en = 0; /* DQS# Enable: 0=enable, 1=disable */ - unsigned int ocd = 0; /* 0x0=OCD not supported, - 0x7=OCD default state */ - unsigned int rtt; - unsigned int al; /* Posted CAS# additive latency (AL) */ - unsigned int ods = 0; /* Output Drive Strength: - 0 = Full strength (18ohm) - 1 = Reduced strength (4ohm) */ - unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), - 1=Disable (Test/Debug) */ - - /* Mode Register (MR) */ - unsigned int mr; /* Mode Register Definition */ - unsigned int pd; /* Power-Down Mode */ - unsigned int wr; /* Write Recovery */ - unsigned int dll_res; /* DLL Reset */ - unsigned int mode; /* Normal=0 or Test=1 */ - unsigned int caslat = 0;/* CAS# latency */ - /* BT: Burst Type (0=Sequential, 1=Interleaved) */ - unsigned int bt; - unsigned int bl; /* BL: Burst Length */ - -#if defined(CONFIG_FSL_DDR2) - const unsigned int mclk_ps = get_memory_clk_period_ps(); -#endif - dqs_en = !popts->dqs_config; - rtt = fsl_ddr_get_rtt(); - - al = additive_latency; - - esdmode = (0 - | ((mrs & 0x3) << 14) - | ((outputs & 0x1) << 12) - | ((rdqs_en & 0x1) << 11) - | ((dqs_en & 0x1) << 10) - | ((ocd & 0x7) << 7) - | ((rtt & 0x2) << 5) /* rtt field is split */ - | ((al & 0x7) << 3) - | ((rtt & 0x1) << 2) /* rtt field is split */ - | ((ods & 0x1) << 1) - | ((dll_en & 0x1) << 0) - ); - - mr = 0; /* FIXME: CHECKME */ - - /* - * 0 = Fast Exit (Normal) - * 1 = Slow Exit (Low Power) - */ - pd = 0; - -#if defined(CONFIG_FSL_DDR1) - wr = 0; /* Historical */ -#elif defined(CONFIG_FSL_DDR2) - wr = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps - 1; -#endif - dll_res = 0; - mode = 0; - -#if defined(CONFIG_FSL_DDR1) - if (1 <= cas_latency && cas_latency <= 4) { - unsigned char mode_caslat_table[4] = { - 0x5, /* 1.5 clocks */ - 0x2, /* 2.0 clocks */ - 0x6, /* 2.5 clocks */ - 0x3 /* 3.0 clocks */ - }; - caslat = mode_caslat_table[cas_latency - 1]; - } else { - printf("Warning: unknown cas_latency %d\n", cas_latency); - } -#elif defined(CONFIG_FSL_DDR2) - caslat = cas_latency; -#endif - bt = 0; - - switch (popts->burst_length) { - case DDR_BL4: - bl = 2; - break; - case DDR_BL8: - bl = 3; - break; - default: - printf("Error: invalid burst length of %u specified. " - " Defaulting to 4 beats.\n", - popts->burst_length); - bl = 2; - break; - } - - sdmode = (0 - | ((mr & 0x3) << 14) - | ((pd & 0x1) << 12) - | ((wr & 0x7) << 9) - | ((dll_res & 0x1) << 8) - | ((mode & 0x1) << 7) - | ((caslat & 0x7) << 4) - | ((bt & 0x1) << 3) - | ((bl & 0x7) << 0) - ); - - ddr->ddr_sdram_mode = (0 - | ((esdmode & 0xFFFF) << 16) - | ((sdmode & 0xFFFF) << 0) - ); - debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); -} -#endif - -/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */ -static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int init_value; /* Initialization value */ - -#ifdef CONFIG_MEM_INIT_VALUE - init_value = CONFIG_MEM_INIT_VALUE; -#else - init_value = 0xDEADBEEF; -#endif - ddr->ddr_data_init = init_value; -} - -/* - * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL) - * The old controller on the 8540/60 doesn't have this register. - * Hope it's OK to set it (to 0) anyway. - */ -static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts) -{ - unsigned int clk_adjust; /* Clock adjust */ - - clk_adjust = popts->clk_adjust; - ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23; - debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl); -} - -/* DDR Initialization Address (DDR_INIT_ADDR) */ -static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int init_addr = 0; /* Initialization address */ - - ddr->ddr_init_addr = init_addr; -} - -/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */ -static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int uia = 0; /* Use initialization address */ - unsigned int init_ext_addr = 0; /* Initialization address */ - - ddr->ddr_init_ext_addr = (0 - | ((uia & 0x1) << 31) - | (init_ext_addr & 0xF) - ); -} - -/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */ -static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts) -{ - unsigned int rwt = 0; /* Read-to-write turnaround for same CS */ - unsigned int wrt = 0; /* Write-to-read turnaround for same CS */ - unsigned int rrt = 0; /* Read-to-read turnaround for same CS */ - unsigned int wwt = 0; /* Write-to-write turnaround for same CS */ - unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */ - -#if defined(CONFIG_FSL_DDR3) - if (popts->burst_length == DDR_BL8) { - /* We set BL/2 for fixed BL8 */ - rrt = 0; /* BL/2 clocks */ - wwt = 0; /* BL/2 clocks */ - } else { - /* We need to set BL/2 + 2 to BC4 and OTF */ - rrt = 2; /* BL/2 + 2 clocks */ - wwt = 2; /* BL/2 + 2 clocks */ - } - dll_lock = 1; /* tDLLK = 512 clocks from spec */ -#endif - ddr->timing_cfg_4 = (0 - | ((rwt & 0xf) << 28) - | ((wrt & 0xf) << 24) - | ((rrt & 0xf) << 20) - | ((wwt & 0xf) << 16) - | (dll_lock & 0x3) - ); - debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4); -} - -/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */ -static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency) -{ - unsigned int rodt_on = 0; /* Read to ODT on */ - unsigned int rodt_off = 0; /* Read to ODT off */ - unsigned int wodt_on = 0; /* Write to ODT on */ - unsigned int wodt_off = 0; /* Write to ODT off */ - -#if defined(CONFIG_FSL_DDR3) - /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ - rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1; - rodt_off = 4; /* 4 clocks */ - wodt_on = 1; /* 1 clocks */ - wodt_off = 4; /* 4 clocks */ -#endif - - ddr->timing_cfg_5 = (0 - | ((rodt_on & 0x1f) << 24) - | ((rodt_off & 0x7) << 20) - | ((wodt_on & 0x1f) << 12) - | ((wodt_off & 0x7) << 8) - ); - debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5); -} - -/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */ -static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en) -{ - unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */ - /* Normal Operation Full Calibration Time (tZQoper) */ - unsigned int zqoper = 0; - /* Normal Operation Short Calibration Time (tZQCS) */ - unsigned int zqcs = 0; - - if (zq_en) { - zqinit = 9; /* 512 clocks */ - zqoper = 8; /* 256 clocks */ - zqcs = 6; /* 64 clocks */ - } - - ddr->ddr_zq_cntl = (0 - | ((zq_en & 0x1) << 31) - | ((zqinit & 0xF) << 24) - | ((zqoper & 0xF) << 16) - | ((zqcs & 0xF) << 8) - ); - debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl); -} - -/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */ -static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en, - const memctl_options_t *popts) -{ - /* - * First DQS pulse rising edge after margining mode - * is programmed (tWL_MRD) - */ - unsigned int wrlvl_mrd = 0; - /* ODT delay after margining mode is programmed (tWL_ODTEN) */ - unsigned int wrlvl_odten = 0; - /* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */ - unsigned int wrlvl_dqsen = 0; - /* WRLVL_SMPL: Write leveling sample time */ - unsigned int wrlvl_smpl = 0; - /* WRLVL_WLR: Write leveling repeition time */ - unsigned int wrlvl_wlr = 0; - /* WRLVL_START: Write leveling start time */ - unsigned int wrlvl_start = 0; - - /* suggest enable write leveling for DDR3 due to fly-by topology */ - if (wrlvl_en) { - /* tWL_MRD min = 40 nCK, we set it 64 */ - wrlvl_mrd = 0x6; - /* tWL_ODTEN 128 */ - wrlvl_odten = 0x7; - /* tWL_DQSEN min = 25 nCK, we set it 32 */ - wrlvl_dqsen = 0x5; - /* - * Write leveling sample time at least need 6 clocks - * higher than tWLO to allow enough time for progagation - * delay and sampling the prime data bits. - */ - wrlvl_smpl = 0xf; - /* - * Write leveling repetition time - * at least tWLO + 6 clocks clocks - * we set it 64 - */ - wrlvl_wlr = 0x6; - /* - * Write leveling start time - * The value use for the DQS_ADJUST for the first sample - * when write leveling is enabled. It probably needs to be - * overriden per platform. - */ - wrlvl_start = 0x8; - /* - * Override the write leveling sample and start time - * according to specific board - */ - if (popts->wrlvl_override) { - wrlvl_smpl = popts->wrlvl_sample; - wrlvl_start = popts->wrlvl_start; - } - } - - ddr->ddr_wrlvl_cntl = (0 - | ((wrlvl_en & 0x1) << 31) - | ((wrlvl_mrd & 0x7) << 24) - | ((wrlvl_odten & 0x7) << 20) - | ((wrlvl_dqsen & 0x7) << 16) - | ((wrlvl_smpl & 0xf) << 12) - | ((wrlvl_wlr & 0x7) << 8) - | ((wrlvl_start & 0x1F) << 0) - ); - debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl); - ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2; - debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2); - ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3; - debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3); - -} - -/* DDR Self Refresh Counter (DDR_SR_CNTR) */ -static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it) -{ - /* Self Refresh Idle Threshold */ - ddr->ddr_sr_cntr = (sr_it & 0xF) << 16; -} - -static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) -{ - if (popts->addr_hash) { - ddr->ddr_eor = 0x40000000; /* address hash enable */ - puts("Address hashing enabled.\n"); - } -} - -static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) -{ - ddr->ddr_cdr1 = popts->ddr_cdr1; - debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1); -} - -static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) -{ - ddr->ddr_cdr2 = popts->ddr_cdr2; - debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2); -} - -unsigned int -check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int res = 0; - - /* - * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are - * not set at the same time. - */ - if (ddr->ddr_sdram_cfg & 0x10000000 - && ddr->ddr_sdram_cfg & 0x00008000) { - printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] " - " should not be set at the same time.\n"); - res++; - } - - return res; -} - -unsigned int -compute_fsl_memctl_config_regs(const memctl_options_t *popts, - fsl_ddr_cfg_regs_t *ddr, - const common_timing_params_t *common_dimm, - const dimm_params_t *dimm_params, - unsigned int dbw_cap_adj, - unsigned int size_only) -{ - unsigned int i; - unsigned int cas_latency; - unsigned int additive_latency; - unsigned int sr_it; - unsigned int zq_en; - unsigned int wrlvl_en; - unsigned int ip_rev = 0; - unsigned int unq_mrs_en = 0; - int cs_en = 1; - - memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t)); - - if (common_dimm == NULL) { - printf("Error: subset DIMM params struct null pointer\n"); - return 1; - } - - /* - * Process overrides first. - * - * FIXME: somehow add dereated caslat to this - */ - cas_latency = (popts->cas_latency_override) - ? popts->cas_latency_override_value - : common_dimm->lowest_common_SPD_caslat; - - additive_latency = (popts->additive_latency_override) - ? popts->additive_latency_override_value - : common_dimm->additive_latency; - - sr_it = (popts->auto_self_refresh_en) - ? popts->sr_it - : 0; - /* ZQ calibration */ - zq_en = (popts->zq_en) ? 1 : 0; - /* write leveling */ - wrlvl_en = (popts->wrlvl_en) ? 1 : 0; - - /* Chip Select Memory Bounds (CSn_BNDS) */ - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { - unsigned long long ea, sa; - unsigned int cs_per_dimm - = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR; - unsigned int dimm_number - = i / cs_per_dimm; - unsigned long long rank_density - = dimm_params[dimm_number].rank_density >> dbw_cap_adj; - - if (dimm_params[dimm_number].n_ranks == 0) { - debug("Skipping setup of CS%u " - "because n_ranks on DIMM %u is 0\n", i, dimm_number); - continue; - } - if (popts->memctl_interleaving) { - switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { - case FSL_DDR_CS0_CS1_CS2_CS3: - break; - case FSL_DDR_CS0_CS1: - case FSL_DDR_CS0_CS1_AND_CS2_CS3: - if (i > 1) - cs_en = 0; - break; - case FSL_DDR_CS2_CS3: - default: - if (i > 0) - cs_en = 0; - break; - } - sa = common_dimm->base_address; - ea = sa + common_dimm->total_mem - 1; - } else if (!popts->memctl_interleaving) { - /* - * If memory interleaving between controllers is NOT - * enabled, the starting address for each memory - * controller is distinct. However, because rank - * interleaving is enabled, the starting and ending - * addresses of the total memory on that memory - * controller needs to be programmed into its - * respective CS0_BNDS. - */ - switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { - case FSL_DDR_CS0_CS1_CS2_CS3: - sa = common_dimm->base_address; - ea = sa + common_dimm->total_mem - 1; - break; - case FSL_DDR_CS0_CS1_AND_CS2_CS3: - if ((i >= 2) && (dimm_number == 0)) { - sa = dimm_params[dimm_number].base_address + - 2 * rank_density; - ea = sa + 2 * rank_density - 1; - } else { - sa = dimm_params[dimm_number].base_address; - ea = sa + 2 * rank_density - 1; - } - break; - case FSL_DDR_CS0_CS1: - if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { - sa = dimm_params[dimm_number].base_address; - ea = sa + rank_density - 1; - if (i != 1) - sa += (i % cs_per_dimm) * rank_density; - ea += (i % cs_per_dimm) * rank_density; - } else { - sa = 0; - ea = 0; - } - if (i == 0) - ea += rank_density; - break; - case FSL_DDR_CS2_CS3: - if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { - sa = dimm_params[dimm_number].base_address; - ea = sa + rank_density - 1; - if (i != 3) - sa += (i % cs_per_dimm) * rank_density; - ea += (i % cs_per_dimm) * rank_density; - } else { - sa = 0; - ea = 0; - } - if (i == 2) - ea += (rank_density >> dbw_cap_adj); - break; - default: /* No bank(chip-select) interleaving */ - sa = dimm_params[dimm_number].base_address; - ea = sa + rank_density - 1; - if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { - sa += (i % cs_per_dimm) * rank_density; - ea += (i % cs_per_dimm) * rank_density; - } else { - sa = 0; - ea = 0; - } - break; - } - } - - sa >>= 24; - ea >>= 24; - - if (cs_en) { - ddr->cs[i].bnds = (0 - | ((sa & 0xFFF) << 16)/* starting address MSB */ - | ((ea & 0xFFF) << 0) /* ending address MSB */ - ); - } else { - /* setting bnds to 0xffffffff for inactive CS */ - ddr->cs[i].bnds = 0xffffffff; - } - - debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds); - set_csn_config(dimm_number, i, ddr, popts, dimm_params); - set_csn_config_2(i, ddr); - } - - /* - * In the case we only need to compute the ddr sdram size, we only need - * to set csn registers, so return from here. - */ - if (size_only) - return 0; - - set_ddr_eor(ddr, popts); - -#if !defined(CONFIG_FSL_DDR1) - set_timing_cfg_0(ddr, popts, dimm_params); -#endif - - set_timing_cfg_3(ddr, popts, common_dimm, cas_latency); - set_timing_cfg_1(ddr, popts, common_dimm, cas_latency); - set_timing_cfg_2(ddr, popts, common_dimm, - cas_latency, additive_latency); - - set_ddr_cdr1(ddr, popts); - set_ddr_cdr2(ddr, popts); - set_ddr_sdram_cfg(ddr, popts, common_dimm); - ip_rev = fsl_ddr_get_version(); - if (ip_rev > 0x40400) - unq_mrs_en = 1; - - set_ddr_sdram_cfg_2(ddr, popts, unq_mrs_en); - set_ddr_sdram_mode(ddr, popts, common_dimm, - cas_latency, additive_latency, unq_mrs_en); - set_ddr_sdram_mode_2(ddr, popts, common_dimm, unq_mrs_en); - set_ddr_sdram_interval(ddr, popts, common_dimm); - set_ddr_data_init(ddr); - set_ddr_sdram_clk_cntl(ddr, popts); - set_ddr_init_addr(ddr); - set_ddr_init_ext_addr(ddr); - set_timing_cfg_4(ddr, popts); - set_timing_cfg_5(ddr, cas_latency); - - set_ddr_zq_cntl(ddr, zq_en); - set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts); - - set_ddr_sr_cntr(ddr, sr_it); - - set_ddr_sdram_rcw(ddr, popts, common_dimm); - -#ifdef CONFIG_SYS_FSL_DDR_EMU - /* disble DDR training for emulator */ - ddr->debug[2] = 0x00000400; - ddr->debug[4] = 0xff800000; -#endif - return check_fsl_memctl_config_regs(ddr); -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h deleted file mode 100644 index e3b414e666..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2008-2011 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#ifndef FSL_DDR_MAIN_H -#define FSL_DDR_MAIN_H - -#include -#include - -#include "common_timing_params.h" - -#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) -/* - * Bind the main DDR setup driver's generic names - * to this specific DDR technology. - */ -static __inline__ int -compute_dimm_parameters(const generic_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) -{ - return ddr_compute_dimm_parameters(spd, pdimm, dimm_number); -} -#endif - -/* - * Data Structures - * - * All data structures have to be on the stack - */ -#define CONFIG_SYS_NUM_DDR_CTLRS CONFIG_NUM_DDR_CONTROLLERS -#define CONFIG_SYS_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR - -typedef struct { - generic_spd_eeprom_t - spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR]; - struct dimm_params_s - dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR]; - memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS]; - common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS]; - fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS]; -} fsl_ddr_info_t; - -/* Compute steps */ -#define STEP_GET_SPD (1 << 0) -#define STEP_COMPUTE_DIMM_PARMS (1 << 1) -#define STEP_COMPUTE_COMMON_PARMS (1 << 2) -#define STEP_GATHER_OPTS (1 << 3) -#define STEP_ASSIGN_ADDRESSES (1 << 4) -#define STEP_COMPUTE_REGS (1 << 5) -#define STEP_PROGRAM_REGS (1 << 6) -#define STEP_ALL 0xFFF - -unsigned long long -fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, - unsigned int size_only); - -const char *step_to_string(unsigned int step); - -unsigned int compute_fsl_memctl_config_regs(const memctl_options_t *popts, - fsl_ddr_cfg_regs_t *ddr, - const common_timing_params_t *common_dimm, - const dimm_params_t *dimm_parameters, - unsigned int dbw_capacity_adjust, - unsigned int size_only); -unsigned int compute_lowest_common_dimm_parameters( - const dimm_params_t *dimm_params, - common_timing_params_t *outpdimm, - unsigned int number_of_dimms); -unsigned int populate_memctl_options(int all_dimms_registered, - memctl_options_t *popts, - dimm_params_t *pdimm, - unsigned int ctrl_num); -void check_interleaving_options(fsl_ddr_info_t *pinfo); - -unsigned int mclk_to_picos(unsigned int mclk); -unsigned int get_memory_clk_period_ps(void); -unsigned int picos_to_mclk(unsigned int picos); -void fsl_ddr_set_lawbar( - const common_timing_params_t *memctl_common_params, - unsigned int memctl_interleaved, - unsigned int ctrl_num); - -int fsl_ddr_interactive_env_var_exists(void); -unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set); -void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, - unsigned int ctrl_num); - -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); -unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr); - -/* processor specific function */ -void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step); - -/* board specific function */ -int fsl_ddr_get_dimm_params(dimm_params_t *pdimm, - unsigned int controller_number, - unsigned int dimm_number); -#endif diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c deleted file mode 100644 index f137fcee34..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include - -#include "ddr.h" - -/* - * Calculate the Density of each Physical Rank. - * Returned size is in bytes. - * - * Study these table from Byte 31 of JEDEC SPD Spec. - * - * DDR I DDR II - * Bit Size Size - * --- ----- ------ - * 7 high 512MB 512MB - * 6 256MB 256MB - * 5 128MB 128MB - * 4 64MB 16GB - * 3 32MB 8GB - * 2 16MB 4GB - * 1 2GB 2GB - * 0 low 1GB 1GB - * - * Reorder Table to be linear by stripping the bottom - * 2 or 5 bits off and shifting them up to the top. - */ - -static unsigned long long -compute_ranksize(unsigned int mem_type, unsigned char row_dens) -{ - unsigned long long bsize; - - /* Bottom 2 bits up to the top. */ - bsize = ((row_dens >> 2) | ((row_dens & 3) << 6)); - bsize <<= 24ULL; - debug("DDR: DDR I rank density = 0x%16llx\n", bsize); - - return bsize; -} - -/* - * Convert a two-nibble BCD value into a cycle time. - * While the spec calls for nano-seconds, picos are returned. - * - * This implements the tables for bytes 9, 23 and 25 for both - * DDR I and II. No allowance for distinguishing the invalid - * fields absent for DDR I yet present in DDR II is made. - * (That is, cycle times of .25, .33, .66 and .75 ns are - * allowed for both DDR II and I.) - */ -static unsigned int -convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) -{ - /* Table look up the lower nibble, allow DDR I & II. */ - unsigned int tenths_ps[16] = { - 0, - 100, - 200, - 300, - 400, - 500, - 600, - 700, - 800, - 900, - 250, /* This and the next 3 entries valid ... */ - 330, /* ... only for tCK calculations. */ - 660, - 750, - 0, /* undefined */ - 0 /* undefined */ - }; - - unsigned int whole_ns = (spd_val & 0xF0) >> 4; - unsigned int tenth_ns = spd_val & 0x0F; - unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns]; - - return ps; -} - -static unsigned int -convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val) -{ - unsigned int tenth_ns = (spd_val & 0xF0) >> 4; - unsigned int hundredth_ns = spd_val & 0x0F; - unsigned int ps = tenth_ns * 100 + hundredth_ns * 10; - - return ps; -} - -static unsigned int byte40_table_ps[8] = { - 0, - 250, - 330, - 500, - 660, - 750, - 0, /* supposed to be RFC, but not sure what that means */ - 0 /* Undefined */ -}; - -static unsigned int -compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc) -{ - unsigned int trfc_ps; - - trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000 - + byte40_table_ps[(trctrfc_ext >> 1) & 0x7]; - - return trfc_ps; -} - -static unsigned int -compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc) -{ - unsigned int trc_ps; - - trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7]; - - return trc_ps; -} - -/* - * tCKmax from DDR I SPD Byte 43 - * - * Bits 7:2 == whole ns - * Bits 1:0 == quarter ns - * 00 == 0.00 ns - * 01 == 0.25 ns - * 10 == 0.50 ns - * 11 == 0.75 ns - * - * Returns picoseconds. - */ -static unsigned int -compute_tckmax_from_spd_ps(unsigned int byte43) -{ - return (byte43 >> 2) * 1000 + (byte43 & 0x3) * 250; -} - -/* - * Determine Refresh Rate. Ignore self refresh bit on DDR I. - * Table from SPD Spec, Byte 12, converted to picoseconds and - * filled in with "default" normal values. - */ -static unsigned int -determine_refresh_rate_ps(const unsigned int spd_refresh) -{ - unsigned int refresh_time_ps[8] = { - 15625000, /* 0 Normal 1.00x */ - 3900000, /* 1 Reduced .25x */ - 7800000, /* 2 Extended .50x */ - 31300000, /* 3 Extended 2.00x */ - 62500000, /* 4 Extended 4.00x */ - 125000000, /* 5 Extended 8.00x */ - 15625000, /* 6 Normal 1.00x filler */ - 15625000, /* 7 Normal 1.00x filler */ - }; - - return refresh_time_ps[spd_refresh & 0x7]; -} - -/* - * The purpose of this function is to compute a suitable - * CAS latency given the DRAM clock period. The SPD only - * defines at most 3 CAS latencies. Typically the slower in - * frequency the DIMM runs at, the shorter its CAS latency can be. - * If the DIMM is operating at a sufficiently low frequency, - * it may be able to run at a CAS latency shorter than the - * shortest SPD-defined CAS latency. - * - * If a CAS latency is not found, 0 is returned. - * - * Do this by finding in the standard speed bin table the longest - * tCKmin that doesn't exceed the value of mclk_ps (tCK). - * - * An assumption made is that the SDRAM device allows the - * CL to be programmed for a value that is lower than those - * advertised by the SPD. This is not always the case, - * as those modes not defined in the SPD are optional. - * - * CAS latency de-rating based upon values JEDEC Standard No. 79-E - * Table 11. - * - * ordinal 2, ddr1_speed_bins[1] contains tCK for CL=2 - */ - /* CL2.0 CL2.5 CL3.0 */ -unsigned short ddr1_speed_bins[] = {0, 7500, 6000, 5000 }; - -unsigned int -compute_derated_DDR1_CAS_latency(unsigned int mclk_ps) -{ - const unsigned int num_speed_bins = ARRAY_SIZE(ddr1_speed_bins); - unsigned int lowest_tCKmin_found = 0; - unsigned int lowest_tCKmin_CL = 0; - unsigned int i; - - debug("mclk_ps = %u\n", mclk_ps); - - for (i = 0; i < num_speed_bins; i++) { - unsigned int x = ddr1_speed_bins[i]; - debug("i=%u, x = %u, lowest_tCKmin_found = %u\n", - i, x, lowest_tCKmin_found); - if (x && lowest_tCKmin_found <= x && x <= mclk_ps) { - lowest_tCKmin_found = x; - lowest_tCKmin_CL = i + 1; - } - } - - debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL); - - return lowest_tCKmin_CL; -} - -/* - * ddr_compute_dimm_parameters for DDR1 SPD - * - * Compute DIMM parameters based upon the SPD information in spd. - * Writes the results to the dimm_params_t structure pointed by pdimm. - * - * FIXME: use #define for the retvals - */ -unsigned int -ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) -{ - unsigned int retval; - - if (spd->mem_type) { - if (spd->mem_type != SPD_MEMTYPE_DDR) { - printf("DIMM %u: is not a DDR1 SPD.\n", dimm_number); - return 1; - } - } else { - memset(pdimm, 0, sizeof(dimm_params_t)); - return 1; - } - - retval = ddr1_spd_check(spd); - if (retval) { - printf("DIMM %u: failed checksum\n", dimm_number); - return 2; - } - - /* - * The part name in ASCII in the SPD EEPROM is not null terminated. - * Guarantee null termination here by presetting all bytes to 0 - * and copying the part name in ASCII from the SPD onto it - */ - memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); - memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); - - /* DIMM organization parameters */ - pdimm->n_ranks = spd->nrows; - pdimm->rank_density = compute_ranksize(spd->mem_type, spd->bank_dens); - pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; - pdimm->data_width = spd->dataw_lsb; - pdimm->primary_sdram_width = spd->primw; - pdimm->ec_sdram_width = spd->ecw; - - /* - * FIXME: Need to determine registered_dimm status. - * 1 == register buffered - * 0 == unbuffered - */ - pdimm->registered_dimm = 0; /* unbuffered */ - - /* SDRAM device parameters */ - pdimm->n_row_addr = spd->nrow_addr; - pdimm->n_col_addr = spd->ncol_addr; - pdimm->n_banks_per_sdram_device = spd->nbanks; - pdimm->edc_config = spd->config; - pdimm->burst_lengths_bitmask = spd->burstl; - pdimm->row_density = spd->bank_dens; - - /* - * Calculate the Maximum Data Rate based on the Minimum Cycle time. - * The SPD clk_cycle field (tCKmin) is measured in tenths of - * nanoseconds and represented as BCD. - */ - pdimm->tckmin_x_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle); - pdimm->tckmin_x_minus_1_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2); - pdimm->tckmin_x_minus_2_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3); - - pdimm->tckmax_ps = compute_tckmax_from_spd_ps(spd->tckmax); - - /* - * Compute CAS latencies defined by SPD - * The SPD caslat_x should have at least 1 and at most 3 bits set. - * - * If cas_lat after masking is 0, the __ilog2 function returns - * 255 into the variable. This behavior is abused once. - */ - pdimm->caslat_x = __ilog2(spd->cas_lat); - pdimm->caslat_x_minus_1 = __ilog2(spd->cas_lat - & ~(1 << pdimm->caslat_x)); - pdimm->caslat_x_minus_2 = __ilog2(spd->cas_lat - & ~(1 << pdimm->caslat_x) - & ~(1 << pdimm->caslat_x_minus_1)); - - /* Compute CAS latencies below that defined by SPD */ - pdimm->caslat_lowest_derated - = compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps()); - - /* Compute timing parameters */ - pdimm->trcd_ps = spd->trcd * 250; - pdimm->trp_ps = spd->trp * 250; - pdimm->tras_ps = spd->tras * 1000; - - pdimm->twr_ps = mclk_to_picos(3); - pdimm->twtr_ps = mclk_to_picos(1); - pdimm->trfc_ps = compute_trfc_ps_from_spd(0, spd->trfc); - - pdimm->trrd_ps = spd->trrd * 250; - pdimm->trc_ps = compute_trc_ps_from_spd(0, spd->trc); - - pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh); - - pdimm->tis_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup); - pdimm->tih_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold); - pdimm->tds_ps - = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup); - pdimm->tdh_ps - = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); - - pdimm->trtp_ps = mclk_to_picos(2); /* By the book. */ - pdimm->tdqsq_max_ps = spd->tdqsq * 10; - pdimm->tqhs_ps = spd->tqhs * 10; - - return 0; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c deleted file mode 100644 index e4d02e8f61..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include - -#include "ddr.h" -/* - * Calculate the Density of each Physical Rank. - * Returned size is in bytes. - * - * Study these table from Byte 31 of JEDEC SPD Spec. - * - * DDR I DDR II - * Bit Size Size - * --- ----- ------ - * 7 high 512MB 512MB - * 6 256MB 256MB - * 5 128MB 128MB - * 4 64MB 16GB - * 3 32MB 8GB - * 2 16MB 4GB - * 1 2GB 2GB - * 0 low 1GB 1GB - * - * Reorder Table to be linear by stripping the bottom - * 2 or 5 bits off and shifting them up to the top. - * - */ -static unsigned long long -compute_ranksize(unsigned int mem_type, unsigned char row_dens) -{ - unsigned long long bsize; - - /* Bottom 5 bits up to the top. */ - bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)); - bsize <<= 27ULL; - debug("DDR: DDR II rank density = 0x%16llx\n", bsize); - - return bsize; -} - -/* - * Convert a two-nibble BCD value into a cycle time. - * While the spec calls for nano-seconds, picos are returned. - * - * This implements the tables for bytes 9, 23 and 25 for both - * DDR I and II. No allowance for distinguishing the invalid - * fields absent for DDR I yet present in DDR II is made. - * (That is, cycle times of .25, .33, .66 and .75 ns are - * allowed for both DDR II and I.) - */ -static unsigned int -convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) -{ - /* Table look up the lower nibble, allow DDR I & II. */ - unsigned int tenths_ps[16] = { - 0, - 100, - 200, - 300, - 400, - 500, - 600, - 700, - 800, - 900, - 250, /* This and the next 3 entries valid ... */ - 330, /* ... only for tCK calculations. */ - 660, - 750, - 0, /* undefined */ - 0 /* undefined */ - }; - - unsigned int whole_ns = (spd_val & 0xF0) >> 4; - unsigned int tenth_ns = spd_val & 0x0F; - unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns]; - - return ps; -} - -static unsigned int -convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val) -{ - unsigned int tenth_ns = (spd_val & 0xF0) >> 4; - unsigned int hundredth_ns = spd_val & 0x0F; - unsigned int ps = tenth_ns * 100 + hundredth_ns * 10; - - return ps; -} - -static unsigned int byte40_table_ps[8] = { - 0, - 250, - 330, - 500, - 660, - 750, - 0, /* supposed to be RFC, but not sure what that means */ - 0 /* Undefined */ -}; - -static unsigned int -compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc) -{ - unsigned int trfc_ps; - - trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000 - + byte40_table_ps[(trctrfc_ext >> 1) & 0x7]; - - return trfc_ps; -} - -static unsigned int -compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc) -{ - unsigned int trc_ps; - - trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7]; - - return trc_ps; -} - -/* - * Determine Refresh Rate. Ignore self refresh bit on DDR I. - * Table from SPD Spec, Byte 12, converted to picoseconds and - * filled in with "default" normal values. - */ -static unsigned int -determine_refresh_rate_ps(const unsigned int spd_refresh) -{ - unsigned int refresh_time_ps[8] = { - 15625000, /* 0 Normal 1.00x */ - 3900000, /* 1 Reduced .25x */ - 7800000, /* 2 Extended .50x */ - 31300000, /* 3 Extended 2.00x */ - 62500000, /* 4 Extended 4.00x */ - 125000000, /* 5 Extended 8.00x */ - 15625000, /* 6 Normal 1.00x filler */ - 15625000, /* 7 Normal 1.00x filler */ - }; - - return refresh_time_ps[spd_refresh & 0x7]; -} - -/* - * The purpose of this function is to compute a suitable - * CAS latency given the DRAM clock period. The SPD only - * defines at most 3 CAS latencies. Typically the slower in - * frequency the DIMM runs at, the shorter its CAS latency can. - * be. If the DIMM is operating at a sufficiently low frequency, - * it may be able to run at a CAS latency shorter than the - * shortest SPD-defined CAS latency. - * - * If a CAS latency is not found, 0 is returned. - * - * Do this by finding in the standard speed bin table the longest - * tCKmin that doesn't exceed the value of mclk_ps (tCK). - * - * An assumption made is that the SDRAM device allows the - * CL to be programmed for a value that is lower than those - * advertised by the SPD. This is not always the case, - * as those modes not defined in the SPD are optional. - * - * CAS latency de-rating based upon values JEDEC Standard No. 79-2C - * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS, - * and tRC for corresponding bin" - * - * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3 - * Not certain if any good value exists for CL=2 - */ - /* CL2 CL3 CL4 CL5 CL6 CL7*/ -unsigned short ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500, 1875 }; - -unsigned int -compute_derated_DDR2_CAS_latency(unsigned int mclk_ps) -{ - const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins); - unsigned int lowest_tCKmin_found = 0; - unsigned int lowest_tCKmin_CL = 0; - unsigned int i; - - debug("mclk_ps = %u\n", mclk_ps); - - for (i = 0; i < num_speed_bins; i++) { - unsigned int x = ddr2_speed_bins[i]; - debug("i=%u, x = %u, lowest_tCKmin_found = %u\n", - i, x, lowest_tCKmin_found); - if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) { - lowest_tCKmin_found = x; - lowest_tCKmin_CL = i + 2; - } - } - - debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL); - - return lowest_tCKmin_CL; -} - -/* - * ddr_compute_dimm_parameters for DDR2 SPD - * - * Compute DIMM parameters based upon the SPD information in spd. - * Writes the results to the dimm_params_t structure pointed by pdimm. - * - * FIXME: use #define for the retvals - */ -unsigned int -ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) -{ - unsigned int retval; - - if (spd->mem_type) { - if (spd->mem_type != SPD_MEMTYPE_DDR2) { - printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number); - return 1; - } - } else { - memset(pdimm, 0, sizeof(dimm_params_t)); - return 1; - } - - retval = ddr2_spd_check(spd); - if (retval) { - printf("DIMM %u: failed checksum\n", dimm_number); - return 2; - } - - /* - * The part name in ASCII in the SPD EEPROM is not null terminated. - * Guarantee null termination here by presetting all bytes to 0 - * and copying the part name in ASCII from the SPD onto it - */ - memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); - memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); - - /* DIMM organization parameters */ - pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1; - pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens); - pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; - pdimm->data_width = spd->dataw; - pdimm->primary_sdram_width = spd->primw; - pdimm->ec_sdram_width = spd->ecw; - - /* These are all the types defined by the JEDEC DDR2 SPD 1.3 spec */ - switch (spd->dimm_type) { - case DDR2_SPD_DIMMTYPE_RDIMM: - case DDR2_SPD_DIMMTYPE_72B_SO_RDIMM: - case DDR2_SPD_DIMMTYPE_MINI_RDIMM: - /* Registered/buffered DIMMs */ - pdimm->registered_dimm = 1; - break; - - case DDR2_SPD_DIMMTYPE_UDIMM: - case DDR2_SPD_DIMMTYPE_SO_DIMM: - case DDR2_SPD_DIMMTYPE_MICRO_DIMM: - case DDR2_SPD_DIMMTYPE_MINI_UDIMM: - /* Unbuffered DIMMs */ - pdimm->registered_dimm = 0; - break; - - case DDR2_SPD_DIMMTYPE_72B_SO_CDIMM: - default: - printf("unknown dimm_type 0x%02X\n", spd->dimm_type); - return 1; - } - - /* SDRAM device parameters */ - pdimm->n_row_addr = spd->nrow_addr; - pdimm->n_col_addr = spd->ncol_addr; - pdimm->n_banks_per_sdram_device = spd->nbanks; - pdimm->edc_config = spd->config; - pdimm->burst_lengths_bitmask = spd->burstl; - pdimm->row_density = spd->rank_dens; - - /* - * Calculate the Maximum Data Rate based on the Minimum Cycle time. - * The SPD clk_cycle field (tCKmin) is measured in tenths of - * nanoseconds and represented as BCD. - */ - pdimm->tckmin_x_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle); - pdimm->tckmin_x_minus_1_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2); - pdimm->tckmin_x_minus_2_ps - = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3); - - pdimm->tckmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax); - - /* - * Compute CAS latencies defined by SPD - * The SPD caslat_x should have at least 1 and at most 3 bits set. - * - * If cas_lat after masking is 0, the __ilog2 function returns - * 255 into the variable. This behavior is abused once. - */ - pdimm->caslat_x = __ilog2(spd->cas_lat); - pdimm->caslat_x_minus_1 = __ilog2(spd->cas_lat - & ~(1 << pdimm->caslat_x)); - pdimm->caslat_x_minus_2 = __ilog2(spd->cas_lat - & ~(1 << pdimm->caslat_x) - & ~(1 << pdimm->caslat_x_minus_1)); - - /* Compute CAS latencies below that defined by SPD */ - pdimm->caslat_lowest_derated - = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps()); - - /* Compute timing parameters */ - pdimm->trcd_ps = spd->trcd * 250; - pdimm->trp_ps = spd->trp * 250; - pdimm->tras_ps = spd->tras * 1000; - - pdimm->twr_ps = spd->twr * 250; - pdimm->twtr_ps = spd->twtr * 250; - pdimm->trfc_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc); - - pdimm->trrd_ps = spd->trrd * 250; - pdimm->trc_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc); - - pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh); - - pdimm->tis_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup); - pdimm->tih_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold); - pdimm->tds_ps - = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup); - pdimm->tdh_ps - = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); - - pdimm->trtp_ps = spd->trtp * 250; - pdimm->tdqsq_max_ps = spd->tdqsq * 10; - pdimm->tqhs_ps = spd->tqhs * 10; - - return 0; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c deleted file mode 100644 index 4c8645da56..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * Dave Liu - * - * calculate the organization and timing parameter - * from ddr3 spd, please refer to the spec - * JEDEC standard No.21-C 4_01_02_11R18.pdf - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include - -#include "ddr.h" - -/* - * Calculate the Density of each Physical Rank. - * Returned size is in bytes. - * - * each rank size = - * sdram capacity(bit) / 8 * primary bus width / sdram width - * - * where: sdram capacity = spd byte4[3:0] - * primary bus width = spd byte8[2:0] - * sdram width = spd byte7[2:0] - * - * SPD byte4 - sdram density and banks - * bit[3:0] size(bit) size(byte) - * 0000 256Mb 32MB - * 0001 512Mb 64MB - * 0010 1Gb 128MB - * 0011 2Gb 256MB - * 0100 4Gb 512MB - * 0101 8Gb 1GB - * 0110 16Gb 2GB - * - * SPD byte8 - module memory bus width - * bit[2:0] primary bus width - * 000 8bits - * 001 16bits - * 010 32bits - * 011 64bits - * - * SPD byte7 - module organiztion - * bit[2:0] sdram device width - * 000 4bits - * 001 8bits - * 010 16bits - * 011 32bits - * - */ -static unsigned long long -compute_ranksize(const ddr3_spd_eeprom_t *spd) -{ - unsigned long long bsize; - - int nbit_sdram_cap_bsize = 0; - int nbit_primary_bus_width = 0; - int nbit_sdram_width = 0; - - if ((spd->density_banks & 0xf) < 7) - nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28; - if ((spd->bus_width & 0x7) < 4) - nbit_primary_bus_width = (spd->bus_width & 0x7) + 3; - if ((spd->organization & 0x7) < 4) - nbit_sdram_width = (spd->organization & 0x7) + 2; - - bsize = 1ULL << (nbit_sdram_cap_bsize - 3 - + nbit_primary_bus_width - nbit_sdram_width); - - debug("DDR: DDR III rank density = 0x%16llx\n", bsize); - - return bsize; -} - -/* - * ddr_compute_dimm_parameters for DDR3 SPD - * - * Compute DIMM parameters based upon the SPD information in spd. - * Writes the results to the dimm_params_t structure pointed by pdimm. - * - */ -unsigned int -ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number) -{ - unsigned int retval; - unsigned int mtb_ps; - int ftb_10th_ps; - int i; - - if (spd->mem_type) { - if (spd->mem_type != SPD_MEMTYPE_DDR3) { - printf("DIMM %u: is not a DDR3 SPD.\n", dimm_number); - return 1; - } - } else { - memset(pdimm, 0, sizeof(dimm_params_t)); - return 1; - } - - retval = ddr3_spd_check(spd); - if (retval) { - printf("DIMM %u: failed checksum\n", dimm_number); - return 2; - } - - /* - * The part name in ASCII in the SPD EEPROM is not null terminated. - * Guarantee null termination here by presetting all bytes to 0 - * and copying the part name in ASCII from the SPD onto it - */ - memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); - if ((spd->info_size_crc & 0xF) > 1) - memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); - - /* DIMM organization parameters */ - pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; - pdimm->rank_density = compute_ranksize(spd); - pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; - pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); - if ((spd->bus_width >> 3) & 0x3) - pdimm->ec_sdram_width = 8; - else - pdimm->ec_sdram_width = 0; - pdimm->data_width = pdimm->primary_sdram_width - + pdimm->ec_sdram_width; - pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); - - /* These are the types defined by the JEDEC DDR3 SPD spec */ - pdimm->mirrored_dimm = 0; - pdimm->registered_dimm = 0; - switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) { - case DDR3_SPD_MODULETYPE_RDIMM: - case DDR3_SPD_MODULETYPE_MINI_RDIMM: - case DDR3_SPD_MODULETYPE_72B_SO_RDIMM: - /* Registered/buffered DIMMs */ - pdimm->registered_dimm = 1; - for (i = 0; i < 16; i += 2) { - u8 rcw = spd->mod_section.registered.rcw[i/2]; - pdimm->rcw[i] = (rcw >> 0) & 0x0F; - pdimm->rcw[i+1] = (rcw >> 4) & 0x0F; - } - break; - - case DDR3_SPD_MODULETYPE_UDIMM: - case DDR3_SPD_MODULETYPE_SO_DIMM: - case DDR3_SPD_MODULETYPE_MICRO_DIMM: - case DDR3_SPD_MODULETYPE_MINI_UDIMM: - case DDR3_SPD_MODULETYPE_MINI_CDIMM: - case DDR3_SPD_MODULETYPE_72B_SO_UDIMM: - case DDR3_SPD_MODULETYPE_72B_SO_CDIMM: - case DDR3_SPD_MODULETYPE_LRDIMM: - case DDR3_SPD_MODULETYPE_16B_SO_DIMM: - case DDR3_SPD_MODULETYPE_32B_SO_DIMM: - /* Unbuffered DIMMs */ - if (spd->mod_section.unbuffered.addr_mapping & 0x1) - pdimm->mirrored_dimm = 1; - break; - - default: - printf("unknown module_type 0x%02X\n", spd->module_type); - return 1; - } - - /* SDRAM device parameters */ - pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; - pdimm->n_col_addr = (spd->addressing & 0x7) + 9; - pdimm->n_banks_per_sdram_device = 8 << ((spd->density_banks >> 4) & 0x7); - - /* - * The SPD spec has not the ECC bit, - * We consider the DIMM as ECC capability - * when the extension bus exist - */ - if (pdimm->ec_sdram_width) - pdimm->edc_config = 0x02; - else - pdimm->edc_config = 0x00; - - /* - * The SPD spec has not the burst length byte - * but DDR3 spec has nature BL8 and BC4, - * BL8 -bit3, BC4 -bit2 - */ - pdimm->burst_lengths_bitmask = 0x0c; - pdimm->row_density = __ilog2(pdimm->rank_density); - - /* MTB - medium timebase - * The unit in the SPD spec is ns, - * We convert it to ps. - * eg: MTB = 0.125ns (125ps) - */ - mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor; - pdimm->mtb_ps = mtb_ps; - - /* - * FTB - fine timebase - * use 1/10th of ps as our unit to avoid floating point - * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps - */ - ftb_10th_ps = - ((spd->ftb_div & 0xf0) >> 4) * 10 / (spd->ftb_div & 0x0f); - pdimm->ftb_10th_ps = ftb_10th_ps; - /* - * sdram minimum cycle time - * we assume the MTB is 0.125ns - * eg: - * tck_min=15 MTB (1.875ns) ->DDR3-1066 - * =12 MTB (1.5ns) ->DDR3-1333 - * =10 MTB (1.25ns) ->DDR3-1600 - */ - pdimm->tckmin_x_ps = spd->tck_min * mtb_ps + - (spd->fine_tck_min * ftb_10th_ps) / 10; - - /* - * CAS latency supported - * bit4 - CL4 - * bit5 - CL5 - * bit18 - CL18 - */ - pdimm->caslat_x = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4; - - /* - * min CAS latency time - * eg: taa_min = - * DDR3-800D 100 MTB (12.5ns) - * DDR3-1066F 105 MTB (13.125ns) - * DDR3-1333H 108 MTB (13.5ns) - * DDR3-1600H 90 MTB (11.25ns) - */ - pdimm->taa_ps = spd->taa_min * mtb_ps + - (spd->fine_taa_min * ftb_10th_ps) / 10; - - /* - * min write recovery time - * eg: - * twr_min = 120 MTB (15ns) -> all speed grades. - */ - pdimm->twr_ps = spd->twr_min * mtb_ps; - - /* - * min RAS to CAS delay time - * eg: trcd_min = - * DDR3-800 100 MTB (12.5ns) - * DDR3-1066F 105 MTB (13.125ns) - * DDR3-1333H 108 MTB (13.5ns) - * DDR3-1600H 90 MTB (11.25) - */ - pdimm->trcd_ps = spd->trcd_min * mtb_ps + - (spd->fine_trcd_min * ftb_10th_ps) / 10; - - /* - * min row active to row active delay time - * eg: trrd_min = - * DDR3-800(1KB page) 80 MTB (10ns) - * DDR3-1333(1KB page) 48 MTB (6ns) - */ - pdimm->trrd_ps = spd->trrd_min * mtb_ps; - - /* - * min row precharge delay time - * eg: trp_min = - * DDR3-800D 100 MTB (12.5ns) - * DDR3-1066F 105 MTB (13.125ns) - * DDR3-1333H 108 MTB (13.5ns) - * DDR3-1600H 90 MTB (11.25ns) - */ - pdimm->trp_ps = spd->trp_min * mtb_ps + - (spd->fine_trp_min * ftb_10th_ps) / 10; - - /* min active to precharge delay time - * eg: tRAS_min = - * DDR3-800D 300 MTB (37.5ns) - * DDR3-1066F 300 MTB (37.5ns) - * DDR3-1333H 288 MTB (36ns) - * DDR3-1600H 280 MTB (35ns) - */ - pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) | spd->tras_min_lsb) - * mtb_ps; - /* - * min active to actice/refresh delay time - * eg: tRC_min = - * DDR3-800D 400 MTB (50ns) - * DDR3-1066F 405 MTB (50.625ns) - * DDR3-1333H 396 MTB (49.5ns) - * DDR3-1600H 370 MTB (46.25ns) - */ - pdimm->trc_ps = (((spd->tras_trc_ext & 0xf0) << 4) | spd->trc_min_lsb) - * mtb_ps + (spd->fine_trc_min * ftb_10th_ps) / 10; - /* - * min refresh recovery delay time - * eg: tRFC_min = - * 512Mb 720 MTB (90ns) - * 1Gb 880 MTB (110ns) - * 2Gb 1280 MTB (160ns) - */ - pdimm->trfc_ps = ((spd->trfc_min_msb << 8) | spd->trfc_min_lsb) - * mtb_ps; - /* - * min internal write to read command delay time - * eg: twtr_min = 40 MTB (7.5ns) - all speed bins. - * tWRT is at least 4 mclk independent of operating freq. - */ - pdimm->twtr_ps = spd->twtr_min * mtb_ps; - - /* - * min internal read to precharge command delay time - * eg: trtp_min = 40 MTB (7.5ns) - all speed bins. - * tRTP is at least 4 mclk independent of operating freq. - */ - pdimm->trtp_ps = spd->trtp_min * mtb_ps; - - /* - * Average periodic refresh interval - * tREFI = 7.8 us at normal temperature range - * = 3.9 us at ext temperature range - */ - pdimm->refresh_rate_ps = 7800000; - if ((spd->therm_ref_opt & 0x1) && !(spd->therm_ref_opt & 0x2)) { - pdimm->refresh_rate_ps = 3900000; - pdimm->extended_op_srt = 1; - } - - /* - * min four active window delay time - * eg: tfaw_min = - * DDR3-800(1KB page) 320 MTB (40ns) - * DDR3-1066(1KB page) 300 MTB (37.5ns) - * DDR3-1333(1KB page) 240 MTB (30ns) - * DDR3-1600(1KB page) 240 MTB (30ns) - */ - pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) - * mtb_ps; - - return 0; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c deleted file mode 100644 index 3b661129cb..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * Copyright 2010-2012 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. - * Based on code from spd_sdram.c - * Author: James Yang [at freescale.com] - * York Sun [at freescale.com] - */ - -#include -#include -#include - -#include -#include "ddr.h" - -/* Option parameter Structures */ -struct options_string { - const char *option_name; - size_t offset; - unsigned int size; - const char printhex; -}; - -static unsigned int picos_to_mhz(unsigned int picos) -{ - return 1000000 / picos; -} - -static void print_option_table(const struct options_string *table, - int table_size, - const void *base) -{ - unsigned int i; - unsigned int *ptr; - unsigned long long *ptr_l; - - for (i = 0; i < table_size; i++) { - switch (table[i].size) { - case 4: - ptr = (unsigned int *) (base + table[i].offset); - if (table[i].printhex) { - printf("%s = 0x%08X\n", - table[i].option_name, *ptr); - } else { - printf("%s = %u\n", - table[i].option_name, *ptr); - } - break; - case 8: - ptr_l = (unsigned long long *) (base + table[i].offset); - printf("%s = %llu\n", - table[i].option_name, *ptr_l); - break; - default: - printf("Unrecognized size!\n"); - break; - } - } -} - -static int handle_option_table(const struct options_string *table, - int table_size, - void *base, - const char *opt, - const char *val) -{ - unsigned int i; - unsigned int value, *ptr; - unsigned long long value_l, *ptr_l; - - for (i = 0; i < table_size; i++) { - if (strcmp(table[i].option_name, opt) != 0) - continue; - switch (table[i].size) { - case 4: - value = simple_strtoul(val, NULL, 0); - ptr = base + table[i].offset; - *ptr = value; - break; - case 8: - value_l = simple_strtoull(val, NULL, 0); - ptr_l = base + table[i].offset; - *ptr_l = value_l; - break; - default: - printf("Unrecognized size!\n"); - break; - } - return 1; - } - - return 0; -} - -static void fsl_ddr_generic_edit(void *pdata, - void *pend, - unsigned int element_size, - unsigned int element_num, - unsigned int value) -{ - char *pcdata = (char *)pdata; /* BIG ENDIAN ONLY */ - - pcdata += element_num * element_size; - if ((pcdata + element_size) > (char *) pend) { - printf("trying to write past end of data\n"); - return; - } - - switch (element_size) { - case 1: - __raw_writeb(value, pcdata); - break; - case 2: - __raw_writew(value, pcdata); - break; - case 4: - __raw_writel(value, pcdata); - break; - default: - printf("unexpected element size %u\n", element_size); - break; - } -} - -static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo, - unsigned int ctrl_num, - unsigned int dimm_num, - unsigned int element_num, - unsigned int value) -{ - generic_spd_eeprom_t *pspd; - - pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]); - fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value); -} - -#define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \ - sizeof((common_timing_params_t *)0)->x, 0} - -static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo, - unsigned int ctrl_num, - const char *optname_str, - const char *value_str) -{ - common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num]; - - static const struct options_string options[] = { - COMMON_TIMING(tckmin_x_ps), - COMMON_TIMING(tckmax_ps), - COMMON_TIMING(tckmax_max_ps), - COMMON_TIMING(trcd_ps), - COMMON_TIMING(trp_ps), - COMMON_TIMING(tras_ps), - COMMON_TIMING(twr_ps), - COMMON_TIMING(twtr_ps), - COMMON_TIMING(trfc_ps), - COMMON_TIMING(trrd_ps), - COMMON_TIMING(trc_ps), - COMMON_TIMING(refresh_rate_ps), - COMMON_TIMING(tis_ps), - COMMON_TIMING(tih_ps), - COMMON_TIMING(tds_ps), - COMMON_TIMING(tdh_ps), - COMMON_TIMING(trtp_ps), - COMMON_TIMING(tdqsq_max_ps), - COMMON_TIMING(tqhs_ps), - COMMON_TIMING(ndimms_present), - COMMON_TIMING(lowest_common_SPD_caslat), - COMMON_TIMING(highest_common_derated_caslat), - COMMON_TIMING(additive_latency), - COMMON_TIMING(all_dimms_burst_lengths_bitmask), - COMMON_TIMING(all_dimms_registered), - COMMON_TIMING(all_dimms_unbuffered), - COMMON_TIMING(all_dimms_ecc_capable), - COMMON_TIMING(total_mem), - COMMON_TIMING(base_address), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - if (handle_option_table(options, n_opts, p, optname_str, value_str)) - return; - - printf("Error: couldn't find option string %s\n", optname_str); -} - -#define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \ - sizeof((dimm_params_t *)0)->x, 0} - -static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, - unsigned int ctrl_num, - unsigned int dimm_num, - const char *optname_str, - const char *value_str) -{ - dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]); - - static const struct options_string options[] = { - DIMM_PARM(n_ranks), - DIMM_PARM(data_width), - DIMM_PARM(primary_sdram_width), - DIMM_PARM(ec_sdram_width), - DIMM_PARM(registered_dimm), - DIMM_PARM(device_width), - - DIMM_PARM(n_row_addr), - DIMM_PARM(n_col_addr), - DIMM_PARM(edc_config), - DIMM_PARM(n_banks_per_sdram_device), - DIMM_PARM(burst_lengths_bitmask), - DIMM_PARM(row_density), - - DIMM_PARM(tckmin_x_ps), - DIMM_PARM(tckmin_x_minus_1_ps), - DIMM_PARM(tckmin_x_minus_2_ps), - DIMM_PARM(tckmax_ps), - - DIMM_PARM(caslat_x), - DIMM_PARM(caslat_x_minus_1), - DIMM_PARM(caslat_x_minus_2), - - DIMM_PARM(caslat_lowest_derated), - - DIMM_PARM(trcd_ps), - DIMM_PARM(trp_ps), - DIMM_PARM(tras_ps), - DIMM_PARM(twr_ps), - DIMM_PARM(twtr_ps), - DIMM_PARM(trfc_ps), - DIMM_PARM(trrd_ps), - DIMM_PARM(trc_ps), - DIMM_PARM(refresh_rate_ps), - - DIMM_PARM(tis_ps), - DIMM_PARM(tih_ps), - DIMM_PARM(tds_ps), - DIMM_PARM(tdh_ps), - DIMM_PARM(trtp_ps), - DIMM_PARM(tdqsq_max_ps), - DIMM_PARM(tqhs_ps), - - DIMM_PARM(rank_density), - DIMM_PARM(capacity), - DIMM_PARM(base_address), - }; - - static const unsigned int n_opts = ARRAY_SIZE(options); - - if (handle_option_table(options, n_opts, p, optname_str, value_str)) - return; - - printf("couldn't find option string %s\n", optname_str); -} - -static void print_dimm_parameters(const dimm_params_t *pdimm) -{ - static const struct options_string options[] = { - DIMM_PARM(n_ranks), - DIMM_PARM(data_width), - DIMM_PARM(primary_sdram_width), - DIMM_PARM(ec_sdram_width), - DIMM_PARM(registered_dimm), - DIMM_PARM(device_width), - - DIMM_PARM(n_row_addr), - DIMM_PARM(n_col_addr), - DIMM_PARM(edc_config), - DIMM_PARM(n_banks_per_sdram_device), - - DIMM_PARM(tckmin_x_ps), - DIMM_PARM(tckmin_x_minus_1_ps), - DIMM_PARM(tckmin_x_minus_2_ps), - DIMM_PARM(tckmax_ps), - - DIMM_PARM(caslat_x), - DIMM_PARM(taa_ps), - DIMM_PARM(caslat_x_minus_1), - DIMM_PARM(caslat_x_minus_2), - DIMM_PARM(caslat_lowest_derated), - - DIMM_PARM(trcd_ps), - DIMM_PARM(trp_ps), - DIMM_PARM(tras_ps), - DIMM_PARM(twr_ps), - DIMM_PARM(twtr_ps), - DIMM_PARM(trfc_ps), - DIMM_PARM(trrd_ps), - DIMM_PARM(trc_ps), - DIMM_PARM(refresh_rate_ps), - - DIMM_PARM(tis_ps), - DIMM_PARM(tih_ps), - DIMM_PARM(tds_ps), - DIMM_PARM(tdh_ps), - DIMM_PARM(trtp_ps), - DIMM_PARM(tdqsq_max_ps), - DIMM_PARM(tqhs_ps), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - if (pdimm->n_ranks == 0) { - printf("DIMM not present\n"); - return; - } - printf("DIMM organization parameters:\n"); - printf("module part name = %s\n", pdimm->mpart); - printf("rank_density = %llu bytes (%llu megabytes)\n", - pdimm->rank_density, pdimm->rank_density / 0x100000); - printf("capacity = %llu bytes (%llu megabytes)\n", - pdimm->capacity, pdimm->capacity / 0x100000); - printf("burst_lengths_bitmask = %02X\n", - pdimm->burst_lengths_bitmask); - printf("base_addresss = %llu (%08llX %08llX)\n", - pdimm->base_address, - (pdimm->base_address >> 32), - pdimm->base_address & 0xFFFFFFFF); - print_option_table(options, n_opts, pdimm); -} - -static void print_lowest_common_dimm_parameters( - const common_timing_params_t *plcd_dimm_params) -{ - static const struct options_string options[] = { - COMMON_TIMING(tckmax_max_ps), - COMMON_TIMING(trcd_ps), - COMMON_TIMING(trp_ps), - COMMON_TIMING(tras_ps), - COMMON_TIMING(twr_ps), - COMMON_TIMING(twtr_ps), - COMMON_TIMING(trfc_ps), - COMMON_TIMING(trrd_ps), - COMMON_TIMING(trc_ps), - COMMON_TIMING(refresh_rate_ps), - COMMON_TIMING(tis_ps), - COMMON_TIMING(tds_ps), - COMMON_TIMING(tdh_ps), - COMMON_TIMING(trtp_ps), - COMMON_TIMING(tdqsq_max_ps), - COMMON_TIMING(tqhs_ps), - COMMON_TIMING(lowest_common_SPD_caslat), - COMMON_TIMING(highest_common_derated_caslat), - COMMON_TIMING(additive_latency), - COMMON_TIMING(ndimms_present), - COMMON_TIMING(all_dimms_registered), - COMMON_TIMING(all_dimms_unbuffered), - COMMON_TIMING(all_dimms_ecc_capable), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - /* Clock frequencies */ - printf("tckmin_x_ps = %u (%u MHz)\n", - plcd_dimm_params->tckmin_x_ps, - picos_to_mhz(plcd_dimm_params->tckmin_x_ps)); - printf("tckmax_ps = %u (%u MHz)\n", - plcd_dimm_params->tckmax_ps, - picos_to_mhz(plcd_dimm_params->tckmax_ps)); - printf("all_dimms_burst_lengths_bitmask = %02X\n", - plcd_dimm_params->all_dimms_burst_lengths_bitmask); - - print_option_table(options, n_opts, plcd_dimm_params); - - printf("total_mem = %llu (%llu megabytes)\n", - plcd_dimm_params->total_mem, - plcd_dimm_params->total_mem / 0x100000); - printf("base_address = %llu (%llu megabytes)\n", - plcd_dimm_params->base_address, - plcd_dimm_params->base_address / 0x100000); -} - -#define CTRL_OPTIONS(x) {#x, offsetof(memctl_options_t, x), \ - sizeof((memctl_options_t *)0)->x, 0} -#define CTRL_OPTIONS_CS(x, y) {"cs" #x "_" #y, \ - offsetof(memctl_options_t, cs_local_opts[x].y), \ - sizeof((memctl_options_t *)0)->cs_local_opts[x].y, 0} - -static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, - unsigned int ctl_num, - const char *optname_str, - const char *value_str) -{ - memctl_options_t *p = &(pinfo->memctl_opts[ctl_num]); - /* - * This array all on the stack and *computed* each time this - * function is rung. - */ - static const struct options_string options[] = { - CTRL_OPTIONS_CS(0, odt_rd_cfg), - CTRL_OPTIONS_CS(0, odt_wr_cfg), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CTRL_OPTIONS_CS(1, odt_rd_cfg), - CTRL_OPTIONS_CS(1, odt_wr_cfg), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(2, odt_rd_cfg), - CTRL_OPTIONS_CS(2, odt_wr_cfg), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(3, odt_rd_cfg), - CTRL_OPTIONS_CS(3, odt_wr_cfg), -#endif -#if defined(CONFIG_FSL_DDR3) - CTRL_OPTIONS_CS(0, odt_rtt_norm), - CTRL_OPTIONS_CS(0, odt_rtt_wr), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CTRL_OPTIONS_CS(1, odt_rtt_norm), - CTRL_OPTIONS_CS(1, odt_rtt_wr), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(2, odt_rtt_norm), - CTRL_OPTIONS_CS(2, odt_rtt_wr), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(3, odt_rtt_norm), - CTRL_OPTIONS_CS(3, odt_rtt_wr), -#endif -#endif - CTRL_OPTIONS(memctl_interleaving), - CTRL_OPTIONS(memctl_interleaving_mode), - CTRL_OPTIONS(ba_intlv_ctl), - CTRL_OPTIONS(ecc_mode), - CTRL_OPTIONS(ecc_init_using_memctl), - CTRL_OPTIONS(dqs_config), - CTRL_OPTIONS(self_refresh_in_sleep), - CTRL_OPTIONS(dynamic_power), - CTRL_OPTIONS(data_bus_width), - CTRL_OPTIONS(burst_length), - CTRL_OPTIONS(cas_latency_override), - CTRL_OPTIONS(cas_latency_override_value), - CTRL_OPTIONS(use_derated_caslat), - CTRL_OPTIONS(additive_latency_override), - CTRL_OPTIONS(additive_latency_override_value), - CTRL_OPTIONS(clk_adjust), - CTRL_OPTIONS(cpo_override), - CTRL_OPTIONS(write_data_delay), - CTRL_OPTIONS(half_strength_driver_enable), - - /* - * These can probably be changed to 2T_EN and 3T_EN - * (using a leading numerical character) without problem - */ - CTRL_OPTIONS(twot_en), - CTRL_OPTIONS(threet_en), - CTRL_OPTIONS(ap_en), - CTRL_OPTIONS(x4_en), - CTRL_OPTIONS(bstopre), - CTRL_OPTIONS(wrlvl_override), - CTRL_OPTIONS(wrlvl_sample), - CTRL_OPTIONS(wrlvl_start), - CTRL_OPTIONS(rcw_override), - CTRL_OPTIONS(rcw_1), - CTRL_OPTIONS(rcw_2), - CTRL_OPTIONS(ddr_cdr1), - CTRL_OPTIONS(ddr_cdr2), - CTRL_OPTIONS(tcke_clock_pulse_width_ps), - CTRL_OPTIONS(tfaw_window_four_activates_ps), - CTRL_OPTIONS(trwt_override), - CTRL_OPTIONS(trwt), - }; - - static const unsigned int n_opts = ARRAY_SIZE(options); - - if (handle_option_table(options, n_opts, p, - optname_str, value_str)) - return; - - printf("couldn't find option string %s\n", optname_str); -} - -#define CFG_REGS(x) {#x, offsetof(fsl_ddr_cfg_regs_t, x), \ - sizeof((fsl_ddr_cfg_regs_t *)0)->x, 1} -#define CFG_REGS_CS(x, y) {"cs" #x "_" #y, \ - offsetof(fsl_ddr_cfg_regs_t, cs[x].y), \ - sizeof((fsl_ddr_cfg_regs_t *)0)->cs[x].y, 1} - -static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) -{ - unsigned int i; - static const struct options_string options[] = { - CFG_REGS_CS(0, bnds), - CFG_REGS_CS(0, config), - CFG_REGS_CS(0, config_2), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CFG_REGS_CS(1, bnds), - CFG_REGS_CS(1, config), - CFG_REGS_CS(1, config_2), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CFG_REGS_CS(2, bnds), - CFG_REGS_CS(2, config), - CFG_REGS_CS(2, config_2), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CFG_REGS_CS(3, bnds), - CFG_REGS_CS(3, config), - CFG_REGS_CS(3, config_2), -#endif - CFG_REGS(timing_cfg_3), - CFG_REGS(timing_cfg_0), - CFG_REGS(timing_cfg_1), - CFG_REGS(timing_cfg_2), - CFG_REGS(ddr_sdram_cfg), - CFG_REGS(ddr_sdram_cfg_2), - CFG_REGS(ddr_sdram_mode), - CFG_REGS(ddr_sdram_mode_2), - CFG_REGS(ddr_sdram_mode_3), - CFG_REGS(ddr_sdram_mode_4), - CFG_REGS(ddr_sdram_mode_5), - CFG_REGS(ddr_sdram_mode_6), - CFG_REGS(ddr_sdram_mode_7), - CFG_REGS(ddr_sdram_mode_8), - CFG_REGS(ddr_sdram_interval), - CFG_REGS(ddr_data_init), - CFG_REGS(ddr_sdram_clk_cntl), - CFG_REGS(ddr_init_addr), - CFG_REGS(ddr_init_ext_addr), - CFG_REGS(timing_cfg_4), - CFG_REGS(timing_cfg_5), - CFG_REGS(ddr_zq_cntl), - CFG_REGS(ddr_wrlvl_cntl), - CFG_REGS(ddr_wrlvl_cntl_2), - CFG_REGS(ddr_wrlvl_cntl_3), - CFG_REGS(ddr_sr_cntr), - CFG_REGS(ddr_sdram_rcw_1), - CFG_REGS(ddr_sdram_rcw_2), - CFG_REGS(ddr_cdr1), - CFG_REGS(ddr_cdr2), - CFG_REGS(err_disable), - CFG_REGS(err_int_en), - CFG_REGS(ddr_eor), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - print_option_table(options, n_opts, ddr); - - for (i = 0; i < 32; i++) - printf("debug_%02d = 0x%08X\n", i+1, ddr->debug[i]); -} - -static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo, - unsigned int ctrl_num, - const char *regname, - const char *value_str) -{ - unsigned int i; - fsl_ddr_cfg_regs_t *ddr; - char buf[20]; - static const struct options_string options[] = { - CFG_REGS_CS(0, bnds), - CFG_REGS_CS(0, config), - CFG_REGS_CS(0, config_2), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CFG_REGS_CS(1, bnds), - CFG_REGS_CS(1, config), - CFG_REGS_CS(1, config_2), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CFG_REGS_CS(2, bnds), - CFG_REGS_CS(2, config), - CFG_REGS_CS(2, config_2), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) - CFG_REGS_CS(3, bnds), - CFG_REGS_CS(3, config), - CFG_REGS_CS(3, config_2), -#endif - CFG_REGS(timing_cfg_3), - CFG_REGS(timing_cfg_0), - CFG_REGS(timing_cfg_1), - CFG_REGS(timing_cfg_2), - CFG_REGS(ddr_sdram_cfg), - CFG_REGS(ddr_sdram_cfg_2), - CFG_REGS(ddr_sdram_mode), - CFG_REGS(ddr_sdram_mode_2), - CFG_REGS(ddr_sdram_mode_3), - CFG_REGS(ddr_sdram_mode_4), - CFG_REGS(ddr_sdram_mode_5), - CFG_REGS(ddr_sdram_mode_6), - CFG_REGS(ddr_sdram_mode_7), - CFG_REGS(ddr_sdram_mode_8), - CFG_REGS(ddr_sdram_interval), - CFG_REGS(ddr_data_init), - CFG_REGS(ddr_sdram_clk_cntl), - CFG_REGS(ddr_init_addr), - CFG_REGS(ddr_init_ext_addr), - CFG_REGS(timing_cfg_4), - CFG_REGS(timing_cfg_5), - CFG_REGS(ddr_zq_cntl), - CFG_REGS(ddr_wrlvl_cntl), - CFG_REGS(ddr_wrlvl_cntl_2), - CFG_REGS(ddr_wrlvl_cntl_3), - CFG_REGS(ddr_sr_cntr), - CFG_REGS(ddr_sdram_rcw_1), - CFG_REGS(ddr_sdram_rcw_2), - CFG_REGS(ddr_cdr1), - CFG_REGS(ddr_cdr2), - CFG_REGS(err_disable), - CFG_REGS(err_int_en), - CFG_REGS(ddr_sdram_rcw_2), - CFG_REGS(ddr_sdram_rcw_2), - CFG_REGS(ddr_eor), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - debug("fsl_ddr_regs_edit: ctrl_num = %u, " - "regname = %s, value = %s\n", - ctrl_num, regname, value_str); - if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS) - return; - - ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]); - - if (handle_option_table(options, n_opts, ddr, regname, value_str)) - return; - - for (i = 0; i < 32; i++) { - unsigned int value = simple_strtoul(value_str, NULL, 0); - sprintf(buf, "debug_%u", i + 1); - if (strcmp(buf, regname) == 0) { - ddr->debug[i] = value; - return; - } - } - printf("Error: couldn't find register string %s\n", regname); -} - -#define CTRL_OPTIONS_HEX(x) {#x, offsetof(memctl_options_t, x), \ - sizeof((memctl_options_t *)0)->x, 1} - -static void print_memctl_options(const memctl_options_t *popts) -{ - static const struct options_string options[] = { - CTRL_OPTIONS_CS(0, odt_rd_cfg), - CTRL_OPTIONS_CS(0, odt_wr_cfg), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CTRL_OPTIONS_CS(1, odt_rd_cfg), - CTRL_OPTIONS_CS(1, odt_wr_cfg), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(2, odt_rd_cfg), - CTRL_OPTIONS_CS(2, odt_wr_cfg), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) - CTRL_OPTIONS_CS(3, odt_rd_cfg), - CTRL_OPTIONS_CS(3, odt_wr_cfg), -#endif -#if defined(CONFIG_FSL_DDR3) - CTRL_OPTIONS_CS(0, odt_rtt_norm), - CTRL_OPTIONS_CS(0, odt_rtt_wr), -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) - CTRL_OPTIONS_CS(1, odt_rtt_norm), - CTRL_OPTIONS_CS(1, odt_rtt_wr), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) - CTRL_OPTIONS_CS(2, odt_rtt_norm), - CTRL_OPTIONS_CS(2, odt_rtt_wr), -#endif -#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) - CTRL_OPTIONS_CS(3, odt_rtt_norm), - CTRL_OPTIONS_CS(3, odt_rtt_wr), -#endif -#endif - CTRL_OPTIONS(memctl_interleaving), - CTRL_OPTIONS(memctl_interleaving_mode), - CTRL_OPTIONS_HEX(ba_intlv_ctl), - CTRL_OPTIONS(ecc_mode), - CTRL_OPTIONS(ecc_init_using_memctl), - CTRL_OPTIONS(dqs_config), - CTRL_OPTIONS(self_refresh_in_sleep), - CTRL_OPTIONS(dynamic_power), - CTRL_OPTIONS(data_bus_width), - CTRL_OPTIONS(burst_length), - CTRL_OPTIONS(cas_latency_override), - CTRL_OPTIONS(cas_latency_override_value), - CTRL_OPTIONS(use_derated_caslat), - CTRL_OPTIONS(additive_latency_override), - CTRL_OPTIONS(additive_latency_override_value), - CTRL_OPTIONS(clk_adjust), - CTRL_OPTIONS(cpo_override), - CTRL_OPTIONS(write_data_delay), - CTRL_OPTIONS(half_strength_driver_enable), - /* - * These can probably be changed to 2T_EN and 3T_EN - * (using a leading numerical character) without problem - */ - CTRL_OPTIONS(twot_en), - CTRL_OPTIONS(threet_en), - CTRL_OPTIONS(registered_dimm_en), - CTRL_OPTIONS(ap_en), - CTRL_OPTIONS(x4_en), - CTRL_OPTIONS(bstopre), - CTRL_OPTIONS(wrlvl_override), - CTRL_OPTIONS(wrlvl_sample), - CTRL_OPTIONS(wrlvl_start), - CTRL_OPTIONS(rcw_override), - CTRL_OPTIONS(rcw_1), - CTRL_OPTIONS(rcw_2), - CTRL_OPTIONS_HEX(ddr_cdr1), - CTRL_OPTIONS_HEX(ddr_cdr2), - CTRL_OPTIONS(tcke_clock_pulse_width_ps), - CTRL_OPTIONS(tfaw_window_four_activates_ps), - CTRL_OPTIONS(trwt_override), - CTRL_OPTIONS(trwt), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - print_option_table(options, n_opts, popts); -} - -#ifdef CONFIG_FSL_DDR1 -void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd) -{ - unsigned int i; - - printf("%-3d : %02x %s\n", 0, spd->info_size, - " spd->info_size, * 0 # bytes written into serial memory *"); - printf("%-3d : %02x %s\n", 1, spd->chip_size, - " spd->chip_size, * 1 Total # bytes of SPD memory device *"); - printf("%-3d : %02x %s\n", 2, spd->mem_type, - " spd->mem_type, * 2 Fundamental memory type *"); - printf("%-3d : %02x %s\n", 3, spd->nrow_addr, - " spd->nrow_addr, * 3 # of Row Addresses on this assembly *"); - printf("%-3d : %02x %s\n", 4, spd->ncol_addr, - " spd->ncol_addr, * 4 # of Column Addrs on this assembly *"); - printf("%-3d : %02x %s\n", 5, spd->nrows, - " spd->nrows * 5 # of DIMM Banks *"); - printf("%-3d : %02x %s\n", 6, spd->dataw_lsb, - " spd->dataw_lsb, * 6 Data Width lsb of this assembly *"); - printf("%-3d : %02x %s\n", 7, spd->dataw_msb, - " spd->dataw_msb, * 7 Data Width msb of this assembly *"); - printf("%-3d : %02x %s\n", 8, spd->voltage, - " spd->voltage, * 8 Voltage intf std of this assembly *"); - printf("%-3d : %02x %s\n", 9, spd->clk_cycle, - " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *"); - printf("%-3d : %02x %s\n", 10, spd->clk_access, - " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *"); - printf("%-3d : %02x %s\n", 11, spd->config, - " spd->config, * 11 DIMM Configuration type *"); - printf("%-3d : %02x %s\n", 12, spd->refresh, - " spd->refresh, * 12 Refresh Rate/Type *"); - printf("%-3d : %02x %s\n", 13, spd->primw, - " spd->primw, * 13 Primary SDRAM Width *"); - printf("%-3d : %02x %s\n", 14, spd->ecw, - " spd->ecw, * 14 Error Checking SDRAM width *"); - printf("%-3d : %02x %s\n", 15, spd->min_delay, - " spd->min_delay, * 15 Back to Back Random Access *"); - printf("%-3d : %02x %s\n", 16, spd->burstl, - " spd->burstl, * 16 Burst Lengths Supported *"); - printf("%-3d : %02x %s\n", 17, spd->nbanks, - " spd->nbanks, * 17 # of Banks on Each SDRAM Device *"); - printf("%-3d : %02x %s\n", 18, spd->cas_lat, - " spd->cas_lat, * 18 CAS# Latencies Supported *"); - printf("%-3d : %02x %s\n", 19, spd->cs_lat, - " spd->cs_lat, * 19 Chip Select Latency *"); - printf("%-3d : %02x %s\n", 20, spd->write_lat, - " spd->write_lat, * 20 Write Latency/Recovery *"); - printf("%-3d : %02x %s\n", 21, spd->mod_attr, - " spd->mod_attr, * 21 SDRAM Module Attributes *"); - printf("%-3d : %02x %s\n", 22, spd->dev_attr, - " spd->dev_attr, * 22 SDRAM Device Attributes *"); - printf("%-3d : %02x %s\n", 23, spd->clk_cycle2, - " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *"); - printf("%-3d : %02x %s\n", 24, spd->clk_access2, - " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *"); - printf("%-3d : %02x %s\n", 25, spd->clk_cycle3, - " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *"); - printf("%-3d : %02x %s\n", 26, spd->clk_access3, - " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *"); - printf("%-3d : %02x %s\n", 27, spd->trp, - " spd->trp, * 27 Min Row Precharge Time (tRP)*"); - printf("%-3d : %02x %s\n", 28, spd->trrd, - " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *"); - printf("%-3d : %02x %s\n", 29, spd->trcd, - " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *"); - printf("%-3d : %02x %s\n", 30, spd->tras, - " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *"); - printf("%-3d : %02x %s\n", 31, spd->bank_dens, - " spd->bank_dens, * 31 Density of each bank on module *"); - printf("%-3d : %02x %s\n", 32, spd->ca_setup, - " spd->ca_setup, * 32 Cmd + Addr signal input setup time *"); - printf("%-3d : %02x %s\n", 33, spd->ca_hold, - " spd->ca_hold, * 33 Cmd and Addr signal input hold time *"); - printf("%-3d : %02x %s\n", 34, spd->data_setup, - " spd->data_setup, * 34 Data signal input setup time *"); - printf("%-3d : %02x %s\n", 35, spd->data_hold, - " spd->data_hold, * 35 Data signal input hold time *"); - printf("%-3d : %02x %s\n", 36, spd->res_36_40[0], - " spd->res_36_40[0], * 36 Reserved / tWR *"); - printf("%-3d : %02x %s\n", 37, spd->res_36_40[1], - " spd->res_36_40[1], * 37 Reserved / tWTR *"); - printf("%-3d : %02x %s\n", 38, spd->res_36_40[2], - " spd->res_36_40[2], * 38 Reserved / tRTP *"); - printf("%-3d : %02x %s\n", 39, spd->res_36_40[3], - " spd->res_36_40[3], * 39 Reserved / mem_probe *"); - printf("%-3d : %02x %s\n", 40, spd->res_36_40[4], - " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *"); - printf("%-3d : %02x %s\n", 41, spd->trc, - " spd->trc, * 41 Min Active to Auto refresh time tRC *"); - printf("%-3d : %02x %s\n", 42, spd->trfc, - " spd->trfc, * 42 Min Auto to Active period tRFC *"); - printf("%-3d : %02x %s\n", 43, spd->tckmax, - " spd->tckmax, * 43 Max device cycle time tCKmax *"); - printf("%-3d : %02x %s\n", 44, spd->tdqsq, - " spd->tdqsq, * 44 Max DQS to DQ skew *"); - printf("%-3d : %02x %s\n", 45, spd->tqhs, - " spd->tqhs, * 45 Max Read DataHold skew tQHS *"); - printf("%-3d : %02x %s\n", 46, spd->res_46, - " spd->res_46, * 46 Reserved/ PLL Relock time *"); - printf("%-3d : %02x %s\n", 47, spd->dimm_height, - " spd->dimm_height * 47 SDRAM DIMM Height *"); - - printf("%-3d-%3d: ", 48, 61); - - for (i = 0; i < 14; i++) - printf("%02x", spd->res_48_61[i]); - - printf(" * 48-61 IDD in SPD and Reserved space *\n"); - - printf("%-3d : %02x %s\n", 62, spd->spd_rev, - " spd->spd_rev, * 62 SPD Data Revision Code *"); - printf("%-3d : %02x %s\n", 63, spd->cksum, - " spd->cksum, * 63 Checksum for bytes 0-62 *"); - printf("%-3d-%3d: ", 64, 71); - - for (i = 0; i < 8; i++) - printf("%02x", spd->mid[i]); - - printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n"); - printf("%-3d : %02x %s\n", 72, spd->mloc, - " spd->mloc, * 72 Manufacturing Location *"); - - printf("%-3d-%3d: >>", 73, 90); - - for (i = 0; i < 18; i++) - printf("%c", spd->mpart[i]); - - printf("<<* 73 Manufacturer's Part Number *\n"); - - printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1], - "* 91 Revision Code *"); - printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1], - "* 93 Manufacturing Date *"); - printf("%-3d-%3d: ", 95, 98); - - for (i = 0; i < 4; i++) - printf("%02x", spd->sernum[i]); - - printf("* 95 Assembly Serial Number *\n"); - - printf("%-3d-%3d: ", 99, 127); - - for (i = 0; i < 27; i++) - printf("%02x", spd->mspec[i]); - - printf("* 99 Manufacturer Specific Data *\n"); -} -#endif - -#ifdef CONFIG_FSL_DDR2 -void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd) -{ - unsigned int i; - - printf("%-3d : %02x %s\n", 0, spd->info_size, - " spd->info_size, * 0 # bytes written into serial memory *"); - printf("%-3d : %02x %s\n", 1, spd->chip_size, - " spd->chip_size, * 1 Total # bytes of SPD memory device *"); - printf("%-3d : %02x %s\n", 2, spd->mem_type, - " spd->mem_type, * 2 Fundamental memory type *"); - printf("%-3d : %02x %s\n", 3, spd->nrow_addr, - " spd->nrow_addr, * 3 # of Row Addresses on this assembly *"); - printf("%-3d : %02x %s\n", 4, spd->ncol_addr, - " spd->ncol_addr, * 4 # of Column Addrs on this assembly *"); - printf("%-3d : %02x %s\n", 5, spd->mod_ranks, - " spd->mod_ranks * 5 # of Module Rows on this assembly *"); - printf("%-3d : %02x %s\n", 6, spd->dataw, - " spd->dataw, * 6 Data Width of this assembly *"); - printf("%-3d : %02x %s\n", 7, spd->res_7, - " spd->res_7, * 7 Reserved *"); - printf("%-3d : %02x %s\n", 8, spd->voltage, - " spd->voltage, * 8 Voltage intf std of this assembly *"); - printf("%-3d : %02x %s\n", 9, spd->clk_cycle, - " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *"); - printf("%-3d : %02x %s\n", 10, spd->clk_access, - " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *"); - printf("%-3d : %02x %s\n", 11, spd->config, - " spd->config, * 11 DIMM Configuration type *"); - printf("%-3d : %02x %s\n", 12, spd->refresh, - " spd->refresh, * 12 Refresh Rate/Type *"); - printf("%-3d : %02x %s\n", 13, spd->primw, - " spd->primw, * 13 Primary SDRAM Width *"); - printf("%-3d : %02x %s\n", 14, spd->ecw, - " spd->ecw, * 14 Error Checking SDRAM width *"); - printf("%-3d : %02x %s\n", 15, spd->res_15, - " spd->res_15, * 15 Reserved *"); - printf("%-3d : %02x %s\n", 16, spd->burstl, - " spd->burstl, * 16 Burst Lengths Supported *"); - printf("%-3d : %02x %s\n", 17, spd->nbanks, - " spd->nbanks, * 17 # of Banks on Each SDRAM Device *"); - printf("%-3d : %02x %s\n", 18, spd->cas_lat, - " spd->cas_lat, * 18 CAS# Latencies Supported *"); - printf("%-3d : %02x %s\n", 19, spd->mech_char, - " spd->mech_char, * 19 Mechanical Characteristics *"); - printf("%-3d : %02x %s\n", 20, spd->dimm_type, - " spd->dimm_type, * 20 DIMM type *"); - printf("%-3d : %02x %s\n", 21, spd->mod_attr, - " spd->mod_attr, * 21 SDRAM Module Attributes *"); - printf("%-3d : %02x %s\n", 22, spd->dev_attr, - " spd->dev_attr, * 22 SDRAM Device Attributes *"); - printf("%-3d : %02x %s\n", 23, spd->clk_cycle2, - " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *"); - printf("%-3d : %02x %s\n", 24, spd->clk_access2, - " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *"); - printf("%-3d : %02x %s\n", 25, spd->clk_cycle3, - " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *"); - printf("%-3d : %02x %s\n", 26, spd->clk_access3, - " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *"); - printf("%-3d : %02x %s\n", 27, spd->trp, - " spd->trp, * 27 Min Row Precharge Time (tRP)*"); - printf("%-3d : %02x %s\n", 28, spd->trrd, - " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *"); - printf("%-3d : %02x %s\n", 29, spd->trcd, - " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *"); - printf("%-3d : %02x %s\n", 30, spd->tras, - " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *"); - printf("%-3d : %02x %s\n", 31, spd->rank_dens, - " spd->rank_dens, * 31 Density of each rank on module *"); - printf("%-3d : %02x %s\n", 32, spd->ca_setup, - " spd->ca_setup, * 32 Cmd + Addr signal input setup time *"); - printf("%-3d : %02x %s\n", 33, spd->ca_hold, - " spd->ca_hold, * 33 Cmd and Addr signal input hold time *"); - printf("%-3d : %02x %s\n", 34, spd->data_setup, - " spd->data_setup, * 34 Data signal input setup time *"); - printf("%-3d : %02x %s\n", 35, spd->data_hold, - " spd->data_hold, * 35 Data signal input hold time *"); - printf("%-3d : %02x %s\n", 36, spd->twr, - " spd->twr, * 36 Write Recovery time tWR *"); - printf("%-3d : %02x %s\n", 37, spd->twtr, - " spd->twtr, * 37 Int write to read delay tWTR *"); - printf("%-3d : %02x %s\n", 38, spd->trtp, - " spd->trtp, * 38 Int read to precharge delay tRTP *"); - printf("%-3d : %02x %s\n", 39, spd->mem_probe, - " spd->mem_probe, * 39 Mem analysis probe characteristics *"); - printf("%-3d : %02x %s\n", 40, spd->trctrfc_ext, - " spd->trctrfc_ext, * 40 Extensions to trc and trfc *"); - printf("%-3d : %02x %s\n", 41, spd->trc, - " spd->trc, * 41 Min Active to Auto refresh time tRC *"); - printf("%-3d : %02x %s\n", 42, spd->trfc, - " spd->trfc, * 42 Min Auto to Active period tRFC *"); - printf("%-3d : %02x %s\n", 43, spd->tckmax, - " spd->tckmax, * 43 Max device cycle time tCKmax *"); - printf("%-3d : %02x %s\n", 44, spd->tdqsq, - " spd->tdqsq, * 44 Max DQS to DQ skew *"); - printf("%-3d : %02x %s\n", 45, spd->tqhs, - " spd->tqhs, * 45 Max Read DataHold skew tQHS *"); - printf("%-3d : %02x %s\n", 46, spd->pll_relock, - " spd->pll_relock, * 46 PLL Relock time *"); - printf("%-3d : %02x %s\n", 47, spd->t_casemax, - " spd->t_casemax, * 47 t_casemax *"); - printf("%-3d : %02x %s\n", 48, spd->psi_ta_dram, - " spd->psi_ta_dram, * 48 Thermal Resistance of DRAM Package " - "from Top (Case) to Ambient (Psi T-A DRAM) *"); - printf("%-3d : %02x %s\n", 49, spd->dt0_mode, - " spd->dt0_mode, * 49 DRAM Case Temperature Rise from " - "Ambient due to Activate-Precharge/Mode Bits " - "(DT0/Mode Bits) *)"); - printf("%-3d : %02x %s\n", 50, spd->dt2n_dt2q, - " spd->dt2n_dt2q, * 50 DRAM Case Temperature Rise from " - "Ambient due to Precharge/Quiet Standby " - "(DT2N/DT2Q) *"); - printf("%-3d : %02x %s\n", 51, spd->dt2p, - " spd->dt2p, * 51 DRAM Case Temperature Rise from " - "Ambient due to Precharge Power-Down (DT2P) *"); - printf("%-3d : %02x %s\n", 52, spd->dt3n, - " spd->dt3n, * 52 DRAM Case Temperature Rise from " - "Ambient due to Active Standby (DT3N) *"); - printf("%-3d : %02x %s\n", 53, spd->dt3pfast, - " spd->dt3pfast, * 53 DRAM Case Temperature Rise from " - "Ambient due to Active Power-Down with Fast PDN Exit " - "(DT3Pfast) *"); - printf("%-3d : %02x %s\n", 54, spd->dt3pslow, - " spd->dt3pslow, * 54 DRAM Case Temperature Rise from " - "Ambient due to Active Power-Down with Slow PDN Exit " - "(DT3Pslow) *"); - printf("%-3d : %02x %s\n", 55, spd->dt4r_dt4r4w, - " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from " - "Ambient due to Page Open Burst Read/DT4R4W Mode Bit " - "(DT4R/DT4R4W Mode Bit) *"); - printf("%-3d : %02x %s\n", 56, spd->dt5b, - " spd->dt5b, * 56 DRAM Case Temperature Rise from " - "Ambient due to Burst Refresh (DT5B) *"); - printf("%-3d : %02x %s\n", 57, spd->dt7, - " spd->dt7, * 57 DRAM Case Temperature Rise from " - "Ambient due to Bank Interleave Reads with " - "Auto-Precharge (DT7) *"); - printf("%-3d : %02x %s\n", 58, spd->psi_ta_pll, - " spd->psi_ta_pll, * 58 Thermal Resistance of PLL Package form" - " Top (Case) to Ambient (Psi T-A PLL) *"); - printf("%-3d : %02x %s\n", 59, spd->psi_ta_reg, - " spd->psi_ta_reg, * 59 Thermal Reisitance of Register Package" - " from Top (Case) to Ambient (Psi T-A Register) *"); - printf("%-3d : %02x %s\n", 60, spd->dtpllactive, - " spd->dtpllactive, * 60 PLL Case Temperature Rise from " - "Ambient due to PLL Active (DT PLL Active) *"); - printf("%-3d : %02x %s\n", 61, spd->dtregact, - " spd->dtregact, " - "* 61 Register Case Temperature Rise from Ambient due to " - "Register Active/Mode Bit (DT Register Active/Mode Bit) *"); - printf("%-3d : %02x %s\n", 62, spd->spd_rev, - " spd->spd_rev, * 62 SPD Data Revision Code *"); - printf("%-3d : %02x %s\n", 63, spd->cksum, - " spd->cksum, * 63 Checksum for bytes 0-62 *"); - - printf("%-3d-%3d: ", 64, 71); - - for (i = 0; i < 8; i++) - printf("%02x", spd->mid[i]); - - printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n"); - - printf("%-3d : %02x %s\n", 72, spd->mloc, - " spd->mloc, * 72 Manufacturing Location *"); - - printf("%-3d-%3d: >>", 73, 90); - for (i = 0; i < 18; i++) - printf("%c", spd->mpart[i]); - - - printf("<<* 73 Manufacturer's Part Number *\n"); - - printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1], - "* 91 Revision Code *"); - printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1], - "* 93 Manufacturing Date *"); - printf("%-3d-%3d: ", 95, 98); - - for (i = 0; i < 4; i++) - printf("%02x", spd->sernum[i]); - - printf("* 95 Assembly Serial Number *\n"); - - printf("%-3d-%3d: ", 99, 127); - for (i = 0; i < 27; i++) - printf("%02x", spd->mspec[i]); - - - printf("* 99 Manufacturer Specific Data *\n"); -} -#endif - -#ifdef CONFIG_FSL_DDR3 -void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd) -{ - unsigned int i; - - /* General Section: Bytes 0-59 */ - -#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, (u8)y); -#define PRINT_NNXXS(n0, n1, x0, x1, s) \ - printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1); - - PRINT_NXS(0, spd->info_size_crc, - "info_size_crc bytes written into serial memory, " - "CRC coverage"); - PRINT_NXS(1, spd->spd_rev, - "spd_rev SPD Revision"); - PRINT_NXS(2, spd->mem_type, - "mem_type Key Byte / DRAM Device Type"); - PRINT_NXS(3, spd->module_type, - "module_type Key Byte / Module Type"); - PRINT_NXS(4, spd->density_banks, - "density_banks SDRAM Density and Banks"); - PRINT_NXS(5, spd->addressing, - "addressing SDRAM Addressing"); - PRINT_NXS(6, spd->module_vdd, - "module_vdd Module Nominal Voltage, VDD"); - PRINT_NXS(7, spd->organization, - "organization Module Organization"); - PRINT_NXS(8, spd->bus_width, - "bus_width Module Memory Bus Width"); - PRINT_NXS(9, spd->ftb_div, - "ftb_div Fine Timebase (FTB) Dividend / Divisor"); - PRINT_NXS(10, spd->mtb_dividend, - "mtb_dividend Medium Timebase (MTB) Dividend"); - PRINT_NXS(11, spd->mtb_divisor, - "mtb_divisor Medium Timebase (MTB) Divisor"); - PRINT_NXS(12, spd->tck_min, - "tck_min SDRAM Minimum Cycle Time"); - PRINT_NXS(13, spd->res_13, - "res_13 Reserved"); - PRINT_NXS(14, spd->caslat_lsb, - "caslat_lsb CAS Latencies Supported, LSB"); - PRINT_NXS(15, spd->caslat_msb, - "caslat_msb CAS Latencies Supported, MSB"); - PRINT_NXS(16, spd->taa_min, - "taa_min Min CAS Latency Time"); - PRINT_NXS(17, spd->twr_min, - "twr_min Min Write REcovery Time"); - PRINT_NXS(18, spd->trcd_min, - "trcd_min Min RAS# to CAS# Delay Time"); - PRINT_NXS(19, spd->trrd_min, - "trrd_min Min Row Active to Row Active Delay Time"); - PRINT_NXS(20, spd->trp_min, - "trp_min Min Row Precharge Delay Time"); - PRINT_NXS(21, spd->tras_trc_ext, - "tras_trc_ext Upper Nibbles for tRAS and tRC"); - PRINT_NXS(22, spd->tras_min_lsb, - "tras_min_lsb Min Active to Precharge Delay Time, LSB"); - PRINT_NXS(23, spd->trc_min_lsb, - "trc_min_lsb Min Active to Active/Refresh Delay Time, LSB"); - PRINT_NXS(24, spd->trfc_min_lsb, - "trfc_min_lsb Min Refresh Recovery Delay Time LSB"); - PRINT_NXS(25, spd->trfc_min_msb, - "trfc_min_msb Min Refresh Recovery Delay Time MSB"); - PRINT_NXS(26, spd->twtr_min, - "twtr_min Min Internal Write to Read Command Delay Time"); - PRINT_NXS(27, spd->trtp_min, - "trtp_min " - "Min Internal Read to Precharge Command Delay Time"); - PRINT_NXS(28, spd->tfaw_msb, - "tfaw_msb Upper Nibble for tFAW"); - PRINT_NXS(29, spd->tfaw_min, - "tfaw_min Min Four Activate Window Delay Time"); - PRINT_NXS(30, spd->opt_features, - "opt_features SDRAM Optional Features"); - PRINT_NXS(31, spd->therm_ref_opt, - "therm_ref_opt SDRAM Thermal and Refresh Opts"); - PRINT_NXS(32, spd->therm_sensor, - "therm_sensor SDRAM Thermal Sensor"); - PRINT_NXS(33, spd->device_type, - "device_type SDRAM Device Type"); - PRINT_NXS(34, spd->fine_tck_min, - "fine_tck_min Fine offset for tCKmin"); - PRINT_NXS(35, spd->fine_taa_min, - "fine_taa_min Fine offset for tAAmin"); - PRINT_NXS(36, spd->fine_trcd_min, - "fine_trcd_min Fine offset for tRCDmin"); - PRINT_NXS(37, spd->fine_trp_min, - "fine_trp_min Fine offset for tRPmin"); - PRINT_NXS(38, spd->fine_trc_min, - "fine_trc_min Fine offset for tRCmin"); - - printf("%-3d-%3d: ", 39, 59); /* Reserved, General Section */ - - for (i = 39; i <= 59; i++) - printf("%02x ", spd->res_39_59[i - 39]); - - puts("\n"); - - switch (spd->module_type) { - case 0x02: /* UDIMM */ - case 0x03: /* SO-DIMM */ - case 0x04: /* Micro-DIMM */ - case 0x06: /* Mini-UDIMM */ - PRINT_NXS(60, spd->mod_section.unbuffered.mod_height, - "mod_height (Unbuffered) Module Nominal Height"); - PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness, - "mod_thickness (Unbuffered) Module Maximum Thickness"); - PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card, - "ref_raw_card (Unbuffered) Reference Raw Card Used"); - PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping, - "addr_mapping (Unbuffered) Address mapping from " - "Edge Connector to DRAM"); - break; - case 0x01: /* RDIMM */ - case 0x05: /* Mini-RDIMM */ - PRINT_NXS(60, spd->mod_section.registered.mod_height, - "mod_height (Registered) Module Nominal Height"); - PRINT_NXS(61, spd->mod_section.registered.mod_thickness, - "mod_thickness (Registered) Module Maximum Thickness"); - PRINT_NXS(62, spd->mod_section.registered.ref_raw_card, - "ref_raw_card (Registered) Reference Raw Card Used"); - PRINT_NXS(63, spd->mod_section.registered.modu_attr, - "modu_attr (Registered) DIMM Module Attributes"); - PRINT_NXS(64, spd->mod_section.registered.thermal, - "thermal (Registered) Thermal Heat " - "Spreader Solution"); - PRINT_NXS(65, spd->mod_section.registered.reg_id_lo, - "reg_id_lo (Registered) Register Manufacturer ID " - "Code, LSB"); - PRINT_NXS(66, spd->mod_section.registered.reg_id_hi, - "reg_id_hi (Registered) Register Manufacturer ID " - "Code, MSB"); - PRINT_NXS(67, spd->mod_section.registered.reg_rev, - "reg_rev (Registered) Register " - "Revision Number"); - PRINT_NXS(68, spd->mod_section.registered.reg_type, - "reg_type (Registered) Register Type"); - for (i = 69; i <= 76; i++) { - printf("%-3d : %02x rcw[%d]\n", i, - spd->mod_section.registered.rcw[i-69], i-69); - } - break; - default: - /* Module-specific Section, Unsupported Module Type */ - printf("%-3d-%3d: ", 60, 116); - - for (i = 60; i <= 116; i++) - printf("%02x", spd->mod_section.uc[i - 60]); - - break; - } - - /* Unique Module ID: Bytes 117-125 */ - PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106"); - PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106"); - PRINT_NXS(119, spd->mloc, "Mfg Location"); - PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date"); - - printf("%-3d-%3d: ", 122, 125); - - for (i = 122; i <= 125; i++) - printf("%02x ", spd->sernum[i - 122]); - printf(" Module Serial Number\n"); - - /* CRC: Bytes 126-127 */ - PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], " SPD CRC"); - - /* Other Manufacturer Fields and User Space: Bytes 128-255 */ - printf("%-3d-%3d: ", 128, 145); - for (i = 128; i <= 145; i++) - printf("%02x ", spd->mpart[i - 128]); - printf(" Mfg's Module Part Number\n"); - - PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1], - "Module Revision code"); - - PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106"); - PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106"); - - printf("%-3d-%3d: ", 150, 175); - for (i = 150; i <= 175; i++) - printf("%02x ", spd->msd[i - 150]); - printf(" Mfg's Specific Data\n"); - - printf("%-3d-%3d: ", 176, 255); - for (i = 176; i <= 255; i++) - printf("%02x", spd->cust[i - 176]); - printf(" Mfg's Specific Data\n"); - -} -#endif - -static inline void generic_spd_dump(const generic_spd_eeprom_t *spd) -{ -#if defined(CONFIG_FSL_DDR1) - ddr1_spd_dump(spd); -#elif defined(CONFIG_FSL_DDR2) - ddr2_spd_dump(spd); -#elif defined(CONFIG_FSL_DDR3) - ddr3_spd_dump(spd); -#endif -} - -static void fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo, - unsigned int ctrl_mask, - unsigned int dimm_mask, - unsigned int do_mask) -{ - unsigned int i, j, retval; - - /* STEP 1: DIMM SPD data */ - if (do_mask & STEP_GET_SPD) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - if (!(dimm_mask & (1 << j))) - continue; - - printf("SPD info: Controller=%u " - "DIMM=%u\n", i, j); - generic_spd_dump( - &(pinfo->spd_installed_dimms[i][j])); - printf("\n"); - } - printf("\n"); - } - printf("\n"); - } - - /* STEP 2: DIMM Parameters */ - if (do_mask & STEP_COMPUTE_DIMM_PARMS) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - if (!(dimm_mask & (1 << j))) - continue; - printf("DIMM parameters: Controller=%u " - "DIMM=%u\n", i, j); - print_dimm_parameters( - &(pinfo->dimm_params[i][j])); - printf("\n"); - } - printf("\n"); - } - printf("\n"); - } - - /* STEP 3: Common Parameters */ - if (do_mask & STEP_COMPUTE_COMMON_PARMS) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - printf("\"lowest common\" DIMM parameters: " - "Controller=%u\n", i); - print_lowest_common_dimm_parameters( - &pinfo->common_timing_params[i]); - printf("\n"); - } - printf("\n"); - } - - /* STEP 4: User Configuration Options */ - if (do_mask & STEP_GATHER_OPTS) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - printf("User Config Options: Controller=%u\n", i); - print_memctl_options(&pinfo->memctl_opts[i]); - printf("\n"); - } - printf("\n"); - } - - /* STEP 5: Address assignment */ - if (do_mask & STEP_ASSIGN_ADDRESSES) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - printf("Address Assignment: Controller=%u " - "DIMM=%u\n", i, j); - printf("Don't have this functionality yet\n"); - } - printf("\n"); - } - printf("\n"); - } - - /* STEP 6: computed controller register values */ - if (do_mask & STEP_COMPUTE_REGS) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (!(ctrl_mask & (1 << i))) - continue; - printf("Computed Register Values: Controller=%u\n", i); - print_fsl_memctl_config_regs( - &pinfo->fsl_ddr_config_reg[i]); - retval = check_fsl_memctl_config_regs( - &pinfo->fsl_ddr_config_reg[i]); - if (retval) { - printf("check_fsl_memctl_config_regs " - "result = %u\n", retval); - } - printf("\n"); - } - printf("\n"); - } -} - -struct data_strings { - const char *data_name; - unsigned int step_mask; - unsigned int dimm_number_required; -}; - -#define DATA_OPTIONS(name, step, dimm) {#name, step, dimm} - -static unsigned int fsl_ddr_parse_interactive_cmd( - char **argv, - int argc, - unsigned int *pstep_mask, - unsigned int *pctlr_mask, - unsigned int *pdimm_mask, - unsigned int *pdimm_number_required - ) { - - static const struct data_strings options[] = { - DATA_OPTIONS(spd, STEP_GET_SPD, 1), - DATA_OPTIONS(dimmparms, STEP_COMPUTE_DIMM_PARMS, 1), - DATA_OPTIONS(commonparms, STEP_COMPUTE_COMMON_PARMS, 0), - DATA_OPTIONS(opts, STEP_GATHER_OPTS, 0), - DATA_OPTIONS(addresses, STEP_ASSIGN_ADDRESSES, 0), - DATA_OPTIONS(regs, STEP_COMPUTE_REGS, 0), - }; - static const unsigned int n_opts = ARRAY_SIZE(options); - - unsigned int i, j; - unsigned int error = 0; - - for (i = 1; i < argc; i++) { - unsigned int matched = 0; - - for (j = 0; j < n_opts; j++) { - if (strcmp(options[j].data_name, argv[i]) != 0) - continue; - *pstep_mask |= options[j].step_mask; - *pdimm_number_required = - options[j].dimm_number_required; - matched = 1; - break; - } - - if (matched) - continue; - - if (argv[i][0] == 'c') { - char c = argv[i][1]; - if (isdigit(c)) - *pctlr_mask |= 1 << (c - '0'); - continue; - } - - if (argv[i][0] == 'd') { - char c = argv[i][1]; - if (isdigit(c)) - *pdimm_mask |= 1 << (c - '0'); - continue; - } - - printf("unknown arg %s\n", argv[i]); - *pstep_mask = 0; - error = 1; - break; - } - - return error; -} - -int fsl_ddr_interactive_env_var_exists(void) -{ - char buffer[CONFIG_SYS_CBSIZE]; - - if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0) - return 1; - - return 0; -} - -unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set) -{ - unsigned long long ddrsize; - const char *prompt = "FSL DDR>"; - char buffer[CONFIG_SYS_CBSIZE]; - char buffer2[CONFIG_SYS_CBSIZE]; - char *p = NULL; - char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ - int argc; - unsigned int next_step = STEP_GET_SPD; - const char *usage = { - "commands:\n" - "print print SPD and intermediate computed data\n" - "reset reboot machine\n" - "recompute reload SPD and options to default and recompute regs\n" - "edit modify spd, parameter, or option\n" - "compute recompute registers from current next_step to end\n" - "copy copy parameters\n" - "next_step shows current next_step\n" - "help this message\n" - "go program the memory controller and continue with u-boot\n" - }; - - if (var_is_set) { - if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) { - p = buffer2; - } else { - var_is_set = 0; - } - } - - /* - * The strategy for next_step is that it points to the next - * step in the computation process that needs to be done. - */ - while (1) { - if (var_is_set) { - char *pend = strchr(p, ';'); - if (pend) { - /* found command separator, copy sub-command */ - *pend = '\0'; - strcpy(buffer, p); - p = pend + 1; - } else { - /* separator not found, copy whole string */ - strcpy(buffer, p); - p = NULL; - var_is_set = 0; - } - } else { - /* - * No need to worry for buffer overflow here in - * this function; readline() maxes out at CFG_CBSIZE - */ - readline_into_buffer(prompt, buffer, 0); - } - argc = parse_line(buffer, argv); - if (argc == 0) - continue; - - - if (strcmp(argv[0], "help") == 0) { - puts(usage); - continue; - } - - if (strcmp(argv[0], "next_step") == 0) { - printf("next_step = 0x%02X (%s)\n", - next_step, - step_to_string(next_step)); - continue; - } - - if (strcmp(argv[0], "copy") == 0) { - unsigned int error = 0; - unsigned int step_mask = 0; - unsigned int src_ctlr_mask = 0; - unsigned int src_dimm_mask = 0; - unsigned int dimm_number_required = 0; - unsigned int src_ctlr_num = 0; - unsigned int src_dimm_num = 0; - unsigned int dst_ctlr_num = -1; - unsigned int dst_dimm_num = -1; - unsigned int i, num_dest_parms; - - if (argc == 1) { - printf("copy \n"); - continue; - } - - error = fsl_ddr_parse_interactive_cmd( - argv, argc, - &step_mask, - &src_ctlr_mask, - &src_dimm_mask, - &dimm_number_required - ); - - /* XXX: only dimm_number_required and step_mask will - be used by this function. Parse the controller and - DIMM number separately because it is easier. */ - - if (error) - continue; - - /* parse source destination controller / DIMM */ - - num_dest_parms = dimm_number_required ? 2 : 1; - - for (i = 0; i < argc; i++) { - if (argv[i][0] == 'c') { - char c = argv[i][1]; - if (isdigit(c)) { - src_ctlr_num = (c - '0'); - break; - } - } - } - - for (i = 0; i < argc; i++) { - if (argv[i][0] == 'd') { - char c = argv[i][1]; - if (isdigit(c)) { - src_dimm_num = (c - '0'); - break; - } - } - } - - /* parse destination controller / DIMM */ - - for (i = argc - 1; i >= argc - num_dest_parms; i--) { - if (argv[i][0] == 'c') { - char c = argv[i][1]; - if (isdigit(c)) { - dst_ctlr_num = (c - '0'); - break; - } - } - } - - for (i = argc - 1; i >= argc - num_dest_parms; i--) { - if (argv[i][0] == 'd') { - char c = argv[i][1]; - if (isdigit(c)) { - dst_dimm_num = (c - '0'); - break; - } - } - } - - /* TODO: validate inputs */ - - debug("src_ctlr_num = %u, src_dimm_num = %u, dst_ctlr_num = %u, dst_dimm_num = %u, step_mask = %x\n", - src_ctlr_num, src_dimm_num, dst_ctlr_num, dst_dimm_num, step_mask); - - - switch (step_mask) { - - case STEP_GET_SPD: - memcpy(&(pinfo->spd_installed_dimms[dst_ctlr_num][dst_dimm_num]), - &(pinfo->spd_installed_dimms[src_ctlr_num][src_dimm_num]), - sizeof(pinfo->spd_installed_dimms[0][0])); - break; - - case STEP_COMPUTE_DIMM_PARMS: - memcpy(&(pinfo->dimm_params[dst_ctlr_num][dst_dimm_num]), - &(pinfo->dimm_params[src_ctlr_num][src_dimm_num]), - sizeof(pinfo->dimm_params[0][0])); - break; - - case STEP_COMPUTE_COMMON_PARMS: - memcpy(&(pinfo->common_timing_params[dst_ctlr_num]), - &(pinfo->common_timing_params[src_ctlr_num]), - sizeof(pinfo->common_timing_params[0])); - break; - - case STEP_GATHER_OPTS: - memcpy(&(pinfo->memctl_opts[dst_ctlr_num]), - &(pinfo->memctl_opts[src_ctlr_num]), - sizeof(pinfo->memctl_opts[0])); - break; - - /* someday be able to have addresses to copy addresses... */ - - case STEP_COMPUTE_REGS: - memcpy(&(pinfo->fsl_ddr_config_reg[dst_ctlr_num]), - &(pinfo->fsl_ddr_config_reg[src_ctlr_num]), - sizeof(pinfo->memctl_opts[0])); - break; - - default: - printf("unexpected step_mask value\n"); - } - - continue; - - } - - if (strcmp(argv[0], "edit") == 0) { - unsigned int error = 0; - unsigned int step_mask = 0; - unsigned int ctlr_mask = 0; - unsigned int dimm_mask = 0; - char *p_element = NULL; - char *p_value = NULL; - unsigned int dimm_number_required = 0; - unsigned int ctrl_num; - unsigned int dimm_num; - - if (argc == 1) { - /* Only the element and value must be last */ - printf("edit " - " \n"); - printf("for spd, specify byte number for " - "element\n"); - continue; - } - - error = fsl_ddr_parse_interactive_cmd( - argv, argc - 2, - &step_mask, - &ctlr_mask, - &dimm_mask, - &dimm_number_required - ); - - if (error) - continue; - - - /* Check arguments */ - - /* ERROR: If no steps were found */ - if (step_mask == 0) { - printf("Error: No valid steps were specified " - "in argument.\n"); - continue; - } - - /* ERROR: If multiple steps were found */ - if (step_mask & (step_mask - 1)) { - printf("Error: Multiple steps specified in " - "argument.\n"); - continue; - } - - /* ERROR: Controller not specified */ - if (ctlr_mask == 0) { - printf("Error: controller number not " - "specified or no element and " - "value specified\n"); - continue; - } - - if (ctlr_mask & (ctlr_mask - 1)) { - printf("Error: multiple controllers " - "specified, %X\n", ctlr_mask); - continue; - } - - /* ERROR: DIMM number not specified */ - if (dimm_number_required && dimm_mask == 0) { - printf("Error: DIMM number number not " - "specified or no element and " - "value specified\n"); - continue; - } - - if (dimm_mask & (dimm_mask - 1)) { - printf("Error: multipled DIMMs specified\n"); - continue; - } - - p_element = argv[argc - 2]; - p_value = argv[argc - 1]; - - ctrl_num = __ilog2(ctlr_mask); - dimm_num = __ilog2(dimm_mask); - - switch (step_mask) { - case STEP_GET_SPD: - { - unsigned int element_num; - unsigned int value; - - element_num = simple_strtoul(p_element, - NULL, 0); - value = simple_strtoul(p_value, - NULL, 0); - fsl_ddr_spd_edit(pinfo, - ctrl_num, - dimm_num, - element_num, - value); - next_step = STEP_COMPUTE_DIMM_PARMS; - } - break; - - case STEP_COMPUTE_DIMM_PARMS: - fsl_ddr_dimm_parameters_edit( - pinfo, ctrl_num, dimm_num, - p_element, p_value); - next_step = STEP_COMPUTE_COMMON_PARMS; - break; - - case STEP_COMPUTE_COMMON_PARMS: - lowest_common_dimm_parameters_edit(pinfo, - ctrl_num, p_element, p_value); - next_step = STEP_GATHER_OPTS; - break; - - case STEP_GATHER_OPTS: - fsl_ddr_options_edit(pinfo, ctrl_num, - p_element, p_value); - next_step = STEP_ASSIGN_ADDRESSES; - break; - - case STEP_ASSIGN_ADDRESSES: - printf("editing of address assignment " - "not yet implemented\n"); - break; - - case STEP_COMPUTE_REGS: - { - fsl_ddr_regs_edit(pinfo, - ctrl_num, - p_element, - p_value); - next_step = STEP_PROGRAM_REGS; - } - break; - - default: - printf("programming error\n"); - while (1) - ; - break; - } - continue; - } - - if (strcmp(argv[0], "reset") == 0) { - /* - * Reboot machine. - * Args don't seem to matter because this - * doesn't return - */ - do_reset(NULL, 0, 0, NULL); - printf("Reset didn't work\n"); - } - - if (strcmp(argv[0], "recompute") == 0) { - /* - * Recalculate everything, starting with - * loading SPD EEPROM from DIMMs - */ - next_step = STEP_GET_SPD; - ddrsize = fsl_ddr_compute(pinfo, next_step, 0); - continue; - } - - if (strcmp(argv[0], "compute") == 0) { - /* - * Compute rest of steps starting at - * the current next_step/ - */ - ddrsize = fsl_ddr_compute(pinfo, next_step, 0); - continue; - } - - if (strcmp(argv[0], "print") == 0) { - unsigned int error = 0; - unsigned int step_mask = 0; - unsigned int ctlr_mask = 0; - unsigned int dimm_mask = 0; - unsigned int dimm_number_required = 0; - - if (argc == 1) { - printf("print [c] [d] [spd] [dimmparms] " - "[commonparms] [opts] [addresses] [regs]\n"); - continue; - } - - error = fsl_ddr_parse_interactive_cmd( - argv, argc, - &step_mask, - &ctlr_mask, - &dimm_mask, - &dimm_number_required - ); - - if (error) - continue; - - /* If no particular controller was found, print all */ - if (ctlr_mask == 0) - ctlr_mask = 0xFF; - - /* If no particular dimm was found, print all dimms. */ - if (dimm_mask == 0) - dimm_mask = 0xFF; - - /* If no steps were found, print all steps. */ - if (step_mask == 0) - step_mask = STEP_ALL; - - fsl_ddr_printinfo(pinfo, ctlr_mask, - dimm_mask, step_mask); - continue; - } - - if (strcmp(argv[0], "go") == 0) { - if (next_step) - ddrsize = fsl_ddr_compute(pinfo, next_step, 0); - break; - } - - printf("unknown command %s\n", argv[0]); - } - - debug("end of memory = %llu\n", (u64)ddrsize); - - return ddrsize; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c deleted file mode 100644 index 332fe25c48..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include - -#include "ddr.h" - -#if defined(CONFIG_FSL_DDR3) -static unsigned int -compute_cas_latency_ddr3(const dimm_params_t *dimm_params, - common_timing_params_t *outpdimm, - unsigned int number_of_dimms) -{ - unsigned int i; - unsigned int taamin_ps = 0; - unsigned int tckmin_x_ps = 0; - unsigned int common_caslat; - unsigned int caslat_actual; - unsigned int retry = 16; - unsigned int tmp; - const unsigned int mclk_ps = get_memory_clk_period_ps(); - - /* compute the common CAS latency supported between slots */ - tmp = dimm_params[0].caslat_x; - for (i = 1; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks) - tmp &= dimm_params[i].caslat_x; - } - common_caslat = tmp; - - /* compute the max tAAmin tCKmin between slots */ - for (i = 0; i < number_of_dimms; i++) { - taamin_ps = max(taamin_ps, dimm_params[i].taa_ps); - tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps); - } - /* validate if the memory clk is in the range of dimms */ - if (mclk_ps < tckmin_x_ps) { - printf("DDR clock (MCLK cycle %u ps) is faster than " - "the slowest DIMM(s) (tCKmin %u ps) can support.\n", - mclk_ps, tckmin_x_ps); - } - /* determine the acutal cas latency */ - caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps; - /* check if the dimms support the CAS latency */ - while (!(common_caslat & (1 << caslat_actual)) && retry > 0) { - caslat_actual++; - retry--; - } - /* once the caculation of caslat_actual is completed - * we must verify that this CAS latency value does not - * exceed tAAmax, which is 20 ns for all DDR3 speed grades - */ - if (caslat_actual * mclk_ps > 20000) { - printf("The choosen cas latency %d is too large\n", - caslat_actual); - } - outpdimm->lowest_common_SPD_caslat = caslat_actual; - - return 0; -} -#endif - -/* - * compute_lowest_common_dimm_parameters() - * - * Determine the worst-case DIMM timing parameters from the set of DIMMs - * whose parameters have been computed into the array pointed to - * by dimm_params. - */ -unsigned int -compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, - common_timing_params_t *outpdimm, - const unsigned int number_of_dimms) -{ - unsigned int i, j; - - unsigned int tckmin_x_ps = 0; - unsigned int tckmax_ps = 0xFFFFFFFF; - unsigned int tckmax_max_ps = 0; - unsigned int trcd_ps = 0; - unsigned int trp_ps = 0; - unsigned int tras_ps = 0; - unsigned int twr_ps = 0; - unsigned int twtr_ps = 0; - unsigned int trfc_ps = 0; - unsigned int trrd_ps = 0; - unsigned int trc_ps = 0; - unsigned int refresh_rate_ps = 0; - unsigned int extended_op_srt = 1; - unsigned int tis_ps = 0; - unsigned int tih_ps = 0; - unsigned int tds_ps = 0; - unsigned int tdh_ps = 0; - unsigned int trtp_ps = 0; - unsigned int tdqsq_max_ps = 0; - unsigned int tqhs_ps = 0; - - unsigned int temp1, temp2; - unsigned int additive_latency = 0; -#if !defined(CONFIG_FSL_DDR3) - const unsigned int mclk_ps = get_memory_clk_period_ps(); - unsigned int lowest_good_caslat; - unsigned int not_ok; - - debug("using mclk_ps = %u\n", mclk_ps); -#endif - - temp1 = 0; - for (i = 0; i < number_of_dimms; i++) { - /* - * If there are no ranks on this DIMM, - * it probably doesn't exist, so skip it. - */ - if (dimm_params[i].n_ranks == 0) { - temp1++; - continue; - } - if (dimm_params[i].n_ranks == 4 && i != 0) { - printf("Found Quad-rank DIMM in wrong bank, ignored." - " Software may not run as expected.\n"); - temp1++; - continue; - } - - /* - * check if quad-rank DIMM is plugged if - * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined - * Only the board with proper design is capable - */ -#ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - if (dimm_params[i].n_ranks == 4 && \ - CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) { - printf("Found Quad-rank DIMM, not able to support."); - temp1++; - continue; - } -#endif - /* - * Find minimum tckmax_ps to find fastest slow speed, - * i.e., this is the slowest the whole system can go. - */ - tckmax_ps = min(tckmax_ps, dimm_params[i].tckmax_ps); - - /* Either find maximum value to determine slowest - * speed, delay, time, period, etc */ - tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps); - tckmax_max_ps = max(tckmax_max_ps, dimm_params[i].tckmax_ps); - trcd_ps = max(trcd_ps, dimm_params[i].trcd_ps); - trp_ps = max(trp_ps, dimm_params[i].trp_ps); - tras_ps = max(tras_ps, dimm_params[i].tras_ps); - twr_ps = max(twr_ps, dimm_params[i].twr_ps); - twtr_ps = max(twtr_ps, dimm_params[i].twtr_ps); - trfc_ps = max(trfc_ps, dimm_params[i].trfc_ps); - trrd_ps = max(trrd_ps, dimm_params[i].trrd_ps); - trc_ps = max(trc_ps, dimm_params[i].trc_ps); - tis_ps = max(tis_ps, dimm_params[i].tis_ps); - tih_ps = max(tih_ps, dimm_params[i].tih_ps); - tds_ps = max(tds_ps, dimm_params[i].tds_ps); - tdh_ps = max(tdh_ps, dimm_params[i].tdh_ps); - trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps); - tqhs_ps = max(tqhs_ps, dimm_params[i].tqhs_ps); - refresh_rate_ps = max(refresh_rate_ps, - dimm_params[i].refresh_rate_ps); - /* extended_op_srt is either 0 or 1, 0 having priority */ - extended_op_srt = min(extended_op_srt, - dimm_params[i].extended_op_srt); - - /* - * Find maximum tdqsq_max_ps to find slowest. - * - * FIXME: is finding the slowest value the correct - * strategy for this parameter? - */ - tdqsq_max_ps = max(tdqsq_max_ps, dimm_params[i].tdqsq_max_ps); - } - - outpdimm->ndimms_present = number_of_dimms - temp1; - - if (temp1 == number_of_dimms) { - debug("no dimms this memory controller\n"); - return 0; - } - - outpdimm->tckmin_x_ps = tckmin_x_ps; - outpdimm->tckmax_ps = tckmax_ps; - outpdimm->tckmax_max_ps = tckmax_max_ps; - outpdimm->trcd_ps = trcd_ps; - outpdimm->trp_ps = trp_ps; - outpdimm->tras_ps = tras_ps; - outpdimm->twr_ps = twr_ps; - outpdimm->twtr_ps = twtr_ps; - outpdimm->trfc_ps = trfc_ps; - outpdimm->trrd_ps = trrd_ps; - outpdimm->trc_ps = trc_ps; - outpdimm->refresh_rate_ps = refresh_rate_ps; - outpdimm->extended_op_srt = extended_op_srt; - outpdimm->tis_ps = tis_ps; - outpdimm->tih_ps = tih_ps; - outpdimm->tds_ps = tds_ps; - outpdimm->tdh_ps = tdh_ps; - outpdimm->trtp_ps = trtp_ps; - outpdimm->tdqsq_max_ps = tdqsq_max_ps; - outpdimm->tqhs_ps = tqhs_ps; - - /* Determine common burst length for all DIMMs. */ - temp1 = 0xff; - for (i = 0; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks) { - temp1 &= dimm_params[i].burst_lengths_bitmask; - } - } - outpdimm->all_dimms_burst_lengths_bitmask = temp1; - - /* Determine if all DIMMs registered buffered. */ - temp1 = temp2 = 0; - for (i = 0; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks) { - if (dimm_params[i].registered_dimm) { - temp1 = 1; -#ifndef CONFIG_SPL_BUILD - printf("Detected RDIMM %s\n", - dimm_params[i].mpart); -#endif - } else { - temp2 = 1; -#ifndef CONFIG_SPL_BUILD - printf("Detected UDIMM %s\n", - dimm_params[i].mpart); -#endif - } - } - } - - outpdimm->all_dimms_registered = 0; - outpdimm->all_dimms_unbuffered = 0; - if (temp1 && !temp2) { - outpdimm->all_dimms_registered = 1; - } else if (!temp1 && temp2) { - outpdimm->all_dimms_unbuffered = 1; - } else { - printf("ERROR: Mix of registered buffered and unbuffered " - "DIMMs detected!\n"); - } - - temp1 = 0; - if (outpdimm->all_dimms_registered) - for (j = 0; j < 16; j++) { - outpdimm->rcw[j] = dimm_params[0].rcw[j]; - for (i = 1; i < number_of_dimms; i++) { - if (!dimm_params[i].n_ranks) - continue; - if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) { - temp1 = 1; - break; - } - } - } - - if (temp1 != 0) - printf("ERROR: Mix different RDIMM detected!\n"); - -#if defined(CONFIG_FSL_DDR3) - if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms)) - return 1; -#else - /* - * Compute a CAS latency suitable for all DIMMs - * - * Strategy for SPD-defined latencies: compute only - * CAS latency defined by all DIMMs. - */ - - /* - * Step 1: find CAS latency common to all DIMMs using bitwise - * operation. - */ - temp1 = 0xFF; - for (i = 0; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks) { - temp2 = 0; - temp2 |= 1 << dimm_params[i].caslat_x; - temp2 |= 1 << dimm_params[i].caslat_x_minus_1; - temp2 |= 1 << dimm_params[i].caslat_x_minus_2; - /* - * FIXME: If there was no entry for X-2 (X-1) in - * the SPD, then caslat_x_minus_2 - * (caslat_x_minus_1) contains either 255 or - * 0xFFFFFFFF because that's what the glorious - * __ilog2 function returns for an input of 0. - * On 32-bit PowerPC, left shift counts with bit - * 26 set (that the value of 255 or 0xFFFFFFFF - * will have), cause the destination register to - * be 0. That is why this works. - */ - temp1 &= temp2; - } - } - - /* - * Step 2: check each common CAS latency against tCK of each - * DIMM's SPD. - */ - lowest_good_caslat = 0; - temp2 = 0; - while (temp1) { - not_ok = 0; - temp2 = __ilog2(temp1); - debug("checking common caslat = %u\n", temp2); - - /* Check if this CAS latency will work on all DIMMs at tCK. */ - for (i = 0; i < number_of_dimms; i++) { - if (!dimm_params[i].n_ranks) { - continue; - } - if (dimm_params[i].caslat_x == temp2) { - if (mclk_ps >= dimm_params[i].tckmin_x_ps) { - debug("CL = %u ok on DIMM %u at tCK=%u" - " ps with its tCKmin_X_ps of %u\n", - temp2, i, mclk_ps, - dimm_params[i].tckmin_x_ps); - continue; - } else { - not_ok++; - } - } - - if (dimm_params[i].caslat_x_minus_1 == temp2) { - unsigned int tckmin_x_minus_1_ps - = dimm_params[i].tckmin_x_minus_1_ps; - if (mclk_ps >= tckmin_x_minus_1_ps) { - debug("CL = %u ok on DIMM %u at " - "tCK=%u ps with its " - "tckmin_x_minus_1_ps of %u\n", - temp2, i, mclk_ps, - tckmin_x_minus_1_ps); - continue; - } else { - not_ok++; - } - } - - if (dimm_params[i].caslat_x_minus_2 == temp2) { - unsigned int tckmin_x_minus_2_ps - = dimm_params[i].tckmin_x_minus_2_ps; - if (mclk_ps >= tckmin_x_minus_2_ps) { - debug("CL = %u ok on DIMM %u at " - "tCK=%u ps with its " - "tckmin_x_minus_2_ps of %u\n", - temp2, i, mclk_ps, - tckmin_x_minus_2_ps); - continue; - } else { - not_ok++; - } - } - } - - if (!not_ok) { - lowest_good_caslat = temp2; - } - - temp1 &= ~(1 << temp2); - } - - debug("lowest common SPD-defined CAS latency = %u\n", - lowest_good_caslat); - outpdimm->lowest_common_SPD_caslat = lowest_good_caslat; - - - /* - * Compute a common 'de-rated' CAS latency. - * - * The strategy here is to find the *highest* dereated cas latency - * with the assumption that all of the DIMMs will support a dereated - * CAS latency higher than or equal to their lowest dereated value. - */ - temp1 = 0; - for (i = 0; i < number_of_dimms; i++) { - temp1 = max(temp1, dimm_params[i].caslat_lowest_derated); - } - outpdimm->highest_common_derated_caslat = temp1; - debug("highest common dereated CAS latency = %u\n", temp1); -#endif /* #if defined(CONFIG_FSL_DDR3) */ - - /* Determine if all DIMMs ECC capable. */ - temp1 = 1; - for (i = 0; i < number_of_dimms; i++) { - if (dimm_params[i].n_ranks && - !(dimm_params[i].edc_config & EDC_ECC)) { - temp1 = 0; - break; - } - } - if (temp1) { - debug("all DIMMs ECC capable\n"); - } else { - debug("Warning: not all DIMMs ECC capable, cant enable ECC\n"); - } - outpdimm->all_dimms_ecc_capable = temp1; - -#ifndef CONFIG_FSL_DDR3 - /* FIXME: move to somewhere else to validate. */ - if (mclk_ps > tckmax_max_ps) { - printf("Warning: some of the installed DIMMs " - "can not operate this slowly.\n"); - return 1; - } -#endif - /* - * Compute additive latency. - * - * For DDR1, additive latency should be 0. - * - * For DDR2, with ODT enabled, use "a value" less than ACTTORW, - * which comes from Trcd, and also note that: - * add_lat + caslat must be >= 4 - * - * For DDR3, we use the AL=0 - * - * When to use additive latency for DDR2: - * - * I. Because you are using CL=3 and need to do ODT on writes and - * want functionality. - * 1. Are you going to use ODT? (Does your board not have - * additional termination circuitry for DQ, DQS, DQS_, - * DM, RDQS, RDQS_ for x4/x8 configs?) - * 2. If so, is your lowest supported CL going to be 3? - * 3. If so, then you must set AL=1 because - * - * WL >= 3 for ODT on writes - * RL = AL + CL - * WL = RL - 1 - * -> - * WL = AL + CL - 1 - * AL + CL - 1 >= 3 - * AL + CL >= 4 - * QED - * - * RL >= 3 for ODT on reads - * RL = AL + CL - * - * Since CL aren't usually less than 2, AL=0 is a minimum, - * so the WL-derived AL should be the -- FIXME? - * - * II. Because you are using auto-precharge globally and want to - * use additive latency (posted CAS) to get more bandwidth. - * 1. Are you going to use auto-precharge mode globally? - * - * Use addtivie latency and compute AL to be 1 cycle less than - * tRCD, i.e. the READ or WRITE command is in the cycle - * immediately following the ACTIVATE command.. - * - * III. Because you feel like it or want to do some sort of - * degraded-performance experiment. - * 1. Do you just want to use additive latency because you feel - * like it? - * - * Validation: AL is less than tRCD, and within the other - * read-to-precharge constraints. - */ - - additive_latency = 0; - -#if defined(CONFIG_FSL_DDR2) - if (lowest_good_caslat < 4) { - additive_latency = (picos_to_mclk(trcd_ps) > lowest_good_caslat) - ? picos_to_mclk(trcd_ps) - lowest_good_caslat : 0; - if (mclk_to_picos(additive_latency) > trcd_ps) { - additive_latency = picos_to_mclk(trcd_ps); - debug("setting additive_latency to %u because it was " - " greater than tRCD_ps\n", additive_latency); - } - } - -#elif defined(CONFIG_FSL_DDR3) - /* - * The system will not use the global auto-precharge mode. - * However, it uses the page mode, so we set AL=0 - */ - additive_latency = 0; -#endif - - /* - * Validate additive latency - * FIXME: move to somewhere else to validate - * - * AL <= tRCD(min) - */ - if (mclk_to_picos(additive_latency) > trcd_ps) { - printf("Error: invalid additive latency exceeds tRCD(min).\n"); - return 1; - } - - /* - * RL = CL + AL; RL >= 3 for ODT_RD_CFG to be enabled - * WL = RL - 1; WL >= 3 for ODT_WL_CFG to be enabled - * ADD_LAT (the register) must be set to a value less - * than ACTTORW if WL = 1, then AL must be set to 1 - * RD_TO_PRE (the register) must be set to a minimum - * tRTP + AL if AL is nonzero - */ - - /* - * Additive latency will be applied only if the memctl option to - * use it. - */ - outpdimm->additive_latency = additive_latency; - - debug("tCKmin_ps = %u\n", outpdimm->tckmin_x_ps); - debug("trcd_ps = %u\n", outpdimm->trcd_ps); - debug("trp_ps = %u\n", outpdimm->trp_ps); - debug("tras_ps = %u\n", outpdimm->tras_ps); - debug("twr_ps = %u\n", outpdimm->twr_ps); - debug("twtr_ps = %u\n", outpdimm->twtr_ps); - debug("trfc_ps = %u\n", outpdimm->trfc_ps); - debug("trrd_ps = %u\n", outpdimm->trrd_ps); - debug("trc_ps = %u\n", outpdimm->trc_ps); - - return 0; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c deleted file mode 100644 index 34d8bc3ac0..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -/* - * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. - * Based on code from spd_sdram.c - * Author: James Yang [at freescale.com] - */ - -#include -#include -#include -#include - -#include "ddr.h" - -void fsl_ddr_set_lawbar( - const common_timing_params_t *memctl_common_params, - unsigned int memctl_interleaved, - unsigned int ctrl_num); -void fsl_ddr_set_intl3r(const unsigned int granule_size); - -#if defined(SPD_EEPROM_ADDRESS) || \ - defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \ - defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4) -#if (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS, -}; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ - [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ -}; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ - [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ -}; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ - [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ - [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ - [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ -}; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ - [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ - [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */ -}; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) -u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { - [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ - [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ - [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ - [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ - [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */ - [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */ -}; - -#endif - -static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) -{ - int ret; - - i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); - - ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, - sizeof(generic_spd_eeprom_t)); - - if (ret) { - if (i2c_address == -#ifdef SPD_EEPROM_ADDRESS - SPD_EEPROM_ADDRESS -#elif defined(SPD_EEPROM_ADDRESS1) - SPD_EEPROM_ADDRESS1 -#endif - ) { - printf("DDR: failed to read SPD from address %u\n", - i2c_address); - } else { - debug("DDR: failed to read SPD from address %u\n", - i2c_address); - } - memset(spd, 0, sizeof(generic_spd_eeprom_t)); - } -} - -__attribute__((weak, alias("__get_spd"))) -void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address); - -void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, - unsigned int ctrl_num) -{ - unsigned int i; - unsigned int i2c_address = 0; - - if (ctrl_num >= CONFIG_NUM_DDR_CONTROLLERS) { - printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); - return; - } - - for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { - i2c_address = spd_i2c_addr[ctrl_num][i]; - get_spd(&(ctrl_dimms_spd[i]), i2c_address); - } -} -#else -void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, - unsigned int ctrl_num) -{ -} -#endif /* SPD_EEPROM_ADDRESSx */ - -/* - * ASSUMPTIONS: - * - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller - * - Same memory data bus width on all controllers - * - * NOTES: - * - * The memory controller and associated documentation use confusing - * terminology when referring to the orgranization of DRAM. - * - * Here is a terminology translation table: - * - * memory controller/documention |industry |this code |signals - * -------------------------------|-----------|-----------|----------------- - * physical bank/bank |rank |rank |chip select (CS) - * logical bank/sub-bank |bank |bank |bank address (BA) - * page/row |row |page |row address - * ??? |column |column |column address - * - * The naming confusion is further exacerbated by the descriptions of the - * memory controller interleaving feature, where accesses are interleaved - * _BETWEEN_ two seperate memory controllers. This is configured only in - * CS0_CONFIG[INTLV_CTL] of each memory controller. - * - * memory controller documentation | number of chip selects - * | per memory controller supported - * --------------------------------|----------------------------------------- - * cache line interleaving | 1 (CS0 only) - * page interleaving | 1 (CS0 only) - * bank interleaving | 1 (CS0 only) - * superbank interleraving | depends on bank (chip select) - * | interleraving [rank interleaving] - * | mode used on every memory controller - * - * Even further confusing is the existence of the interleaving feature - * _WITHIN_ each memory controller. The feature is referred to in - * documentation as chip select interleaving or bank interleaving, - * although it is configured in the DDR_SDRAM_CFG field. - * - * Name of field | documentation name | this code - * -----------------------------|-----------------------|------------------ - * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving - * | interleaving - */ - -const char *step_string_tbl[] = { - "STEP_GET_SPD", - "STEP_COMPUTE_DIMM_PARMS", - "STEP_COMPUTE_COMMON_PARMS", - "STEP_GATHER_OPTS", - "STEP_ASSIGN_ADDRESSES", - "STEP_COMPUTE_REGS", - "STEP_PROGRAM_REGS", - "STEP_ALL" -}; - -const char * step_to_string(unsigned int step) { - - unsigned int s = __ilog2(step); - - if ((1 << s) != step) - return step_string_tbl[7]; - - return step_string_tbl[s]; -} - -static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, - unsigned int dbw_cap_adj[]) -{ - int i, j; - unsigned long long total_mem, current_mem_base, total_ctlr_mem; - unsigned long long rank_density, ctlr_density = 0; - - /* - * If a reduced data width is requested, but the SPD - * specifies a physically wider device, adjust the - * computed dimm capacities accordingly before - * assigning addresses. - */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - unsigned int found = 0; - - switch (pinfo->memctl_opts[i].data_bus_width) { - case 2: - /* 16-bit */ - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - unsigned int dw; - if (!pinfo->dimm_params[i][j].n_ranks) - continue; - dw = pinfo->dimm_params[i][j].primary_sdram_width; - if ((dw == 72 || dw == 64)) { - dbw_cap_adj[i] = 2; - break; - } else if ((dw == 40 || dw == 32)) { - dbw_cap_adj[i] = 1; - break; - } - } - break; - - case 1: - /* 32-bit */ - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - unsigned int dw; - dw = pinfo->dimm_params[i][j].data_width; - if (pinfo->dimm_params[i][j].n_ranks - && (dw == 72 || dw == 64)) { - /* - * FIXME: can't really do it - * like this because this just - * further reduces the memory - */ - found = 1; - break; - } - } - if (found) { - dbw_cap_adj[i] = 1; - } - break; - - case 0: - /* 64-bit */ - break; - - default: - printf("unexpected data bus width " - "specified controller %u\n", i); - return 1; - } - debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); - } - - current_mem_base = 0ull; - total_mem = 0; - if (pinfo->memctl_opts[0].memctl_interleaving) { - rank_density = pinfo->dimm_params[0][0].rank_density >> - dbw_cap_adj[0]; - switch (pinfo->memctl_opts[0].ba_intlv_ctl & - FSL_DDR_CS0_CS1_CS2_CS3) { - case FSL_DDR_CS0_CS1_CS2_CS3: - ctlr_density = 4 * rank_density; - break; - case FSL_DDR_CS0_CS1: - case FSL_DDR_CS0_CS1_AND_CS2_CS3: - ctlr_density = 2 * rank_density; - break; - case FSL_DDR_CS2_CS3: - default: - ctlr_density = rank_density; - break; - } - debug("rank density is 0x%llx, ctlr density is 0x%llx\n", - rank_density, ctlr_density); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (pinfo->memctl_opts[i].memctl_interleaving) { - switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { - case FSL_DDR_CACHE_LINE_INTERLEAVING: - case FSL_DDR_PAGE_INTERLEAVING: - case FSL_DDR_BANK_INTERLEAVING: - case FSL_DDR_SUPERBANK_INTERLEAVING: - total_ctlr_mem = 2 * ctlr_density; - break; - case FSL_DDR_3WAY_1KB_INTERLEAVING: - case FSL_DDR_3WAY_4KB_INTERLEAVING: - case FSL_DDR_3WAY_8KB_INTERLEAVING: - total_ctlr_mem = 3 * ctlr_density; - break; - case FSL_DDR_4WAY_1KB_INTERLEAVING: - case FSL_DDR_4WAY_4KB_INTERLEAVING: - case FSL_DDR_4WAY_8KB_INTERLEAVING: - total_ctlr_mem = 4 * ctlr_density; - break; - default: - panic("Unknown interleaving mode"); - } - pinfo->common_timing_params[i].base_address = - current_mem_base; - pinfo->common_timing_params[i].total_mem = - total_ctlr_mem; - total_mem = current_mem_base + total_ctlr_mem; - debug("ctrl %d base 0x%llx\n", i, current_mem_base); - debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); - } else { - /* when 3rd controller not interleaved */ - current_mem_base = total_mem; - total_ctlr_mem = 0; - pinfo->common_timing_params[i].base_address = - current_mem_base; - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - unsigned long long cap = - pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; - pinfo->dimm_params[i][j].base_address = - current_mem_base; - debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); - current_mem_base += cap; - total_ctlr_mem += cap; - } - debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); - pinfo->common_timing_params[i].total_mem = - total_ctlr_mem; - total_mem += total_ctlr_mem; - } - } - } else { - /* - * Simple linear assignment if memory - * controllers are not interleaved. - */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - total_ctlr_mem = 0; - pinfo->common_timing_params[i].base_address = - current_mem_base; - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - /* Compute DIMM base addresses. */ - unsigned long long cap = - pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; - pinfo->dimm_params[i][j].base_address = - current_mem_base; - debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); - current_mem_base += cap; - total_ctlr_mem += cap; - } - debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); - pinfo->common_timing_params[i].total_mem = - total_ctlr_mem; - total_mem += total_ctlr_mem; - } - } - debug("Total mem by %s is 0x%llx\n", __func__, total_mem); - - return total_mem; -} - -/* Use weak function to allow board file to override the address assignment */ -__attribute__((weak, alias("__step_assign_addresses"))) -unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, - unsigned int dbw_cap_adj[]); - -unsigned long long -fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, - unsigned int size_only) -{ - unsigned int i, j; - unsigned long long total_mem = 0; - int assert_reset; - - fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; - common_timing_params_t *timing_params = pinfo->common_timing_params; - assert_reset = board_need_mem_reset(); - - /* data bus width capacity adjust shift amount */ - unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS]; - - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - dbw_capacity_adjust[i] = 0; - } - - debug("starting at step %u (%s)\n", - start_step, step_to_string(start_step)); - - switch (start_step) { - case STEP_GET_SPD: -#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) - /* STEP 1: Gather all DIMM SPD data */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); - } - - case STEP_COMPUTE_DIMM_PARMS: - /* STEP 2: Compute DIMM parameters from SPD data */ - - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - unsigned int retval; - generic_spd_eeprom_t *spd = - &(pinfo->spd_installed_dimms[i][j]); - dimm_params_t *pdimm = - &(pinfo->dimm_params[i][j]); - - retval = compute_dimm_parameters(spd, pdimm, i); -#ifdef CONFIG_SYS_DDR_RAW_TIMING - if (!i && !j && retval) { - printf("SPD error on controller %d! " - "Trying fallback to raw timing " - "calculation\n", i); - fsl_ddr_get_dimm_params(pdimm, i, j); - } -#else - if (retval == 2) { - printf("Error: compute_dimm_parameters" - " non-zero returned FATAL value " - "for memctl=%u dimm=%u\n", i, j); - return 0; - } -#endif - if (retval) { - debug("Warning: compute_dimm_parameters" - " non-zero return value for memctl=%u " - "dimm=%u\n", i, j); - } - } - } - -#elif defined(CONFIG_SYS_DDR_RAW_TIMING) - case STEP_COMPUTE_DIMM_PARMS: - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { - dimm_params_t *pdimm = - &(pinfo->dimm_params[i][j]); - fsl_ddr_get_dimm_params(pdimm, i, j); - } - } - debug("Filling dimm parameters from board specific file\n"); -#endif - case STEP_COMPUTE_COMMON_PARMS: - /* - * STEP 3: Compute a common set of timing parameters - * suitable for all of the DIMMs on each memory controller - */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - debug("Computing lowest common DIMM" - " parameters for memctl=%u\n", i); - compute_lowest_common_dimm_parameters( - pinfo->dimm_params[i], - &timing_params[i], - CONFIG_DIMM_SLOTS_PER_CTLR); - } - - case STEP_GATHER_OPTS: - /* STEP 4: Gather configuration requirements from user */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - debug("Reloading memory controller " - "configuration options for memctl=%u\n", i); - /* - * This "reloads" the memory controller options - * to defaults. If the user "edits" an option, - * next_step points to the step after this, - * which is currently STEP_ASSIGN_ADDRESSES. - */ - populate_memctl_options( - timing_params[i].all_dimms_registered, - &pinfo->memctl_opts[i], - pinfo->dimm_params[i], i); - /* - * For RDIMMs, JEDEC spec requires clocks to be stable - * before reset signal is deasserted. For the boards - * using fixed parameters, this function should be - * be called from board init file. - */ - if (timing_params[i].all_dimms_registered) - assert_reset = 1; - } - if (assert_reset) { - debug("Asserting mem reset\n"); - board_assert_mem_reset(); - } - - case STEP_ASSIGN_ADDRESSES: - /* STEP 5: Assign addresses to chip selects */ - check_interleaving_options(pinfo); - total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); - - case STEP_COMPUTE_REGS: - /* STEP 6: compute controller register values */ - debug("FSL Memory ctrl register computation\n"); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (timing_params[i].ndimms_present == 0) { - memset(&ddr_reg[i], 0, - sizeof(fsl_ddr_cfg_regs_t)); - continue; - } - - compute_fsl_memctl_config_regs( - &pinfo->memctl_opts[i], - &ddr_reg[i], &timing_params[i], - pinfo->dimm_params[i], - dbw_capacity_adjust[i], - size_only); - } - - default: - break; - } - - { - /* - * Compute the amount of memory available just by - * looking for the highest valid CSn_BNDS value. - * This allows us to also experiment with using - * only CS0 when using dual-rank DIMMs. - */ - unsigned int max_end = 0; - - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) { - fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; - if (reg->cs[j].config & 0x80000000) { - unsigned int end; - /* - * 0xfffffff is a special value we put - * for unused bnds - */ - if (reg->cs[j].bnds == 0xffffffff) - continue; - end = reg->cs[j].bnds & 0xffff; - if (end > max_end) { - max_end = end; - } - } - } - } - - total_mem = 1 + (((unsigned long long)max_end << 24ULL) - | 0xFFFFFFULL); - } - - return total_mem; -} - -/* - * fsl_ddr_sdram() -- this is the main function to be called by - * initdram() in the board file. - * - * It returns amount of memory configured in bytes. - */ -phys_size_t fsl_ddr_sdram(void) -{ - unsigned int i; - unsigned int law_memctl = LAW_TRGT_IF_DDR_1; - unsigned long long total_memory; - fsl_ddr_info_t info; - int deassert_reset; - - /* Reset info structure. */ - memset(&info, 0, sizeof(fsl_ddr_info_t)); - - /* Compute it once normally. */ -#ifdef CONFIG_FSL_DDR_INTERACTIVE - if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */ - total_memory = fsl_ddr_interactive(&info, 0); - } else if (fsl_ddr_interactive_env_var_exists()) { - total_memory = fsl_ddr_interactive(&info, 1); - } else -#endif - total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); - - /* setup 3-way interleaving before enabling DDRC */ - if (info.memctl_opts[0].memctl_interleaving) { - switch (info.memctl_opts[0].memctl_interleaving_mode) { - case FSL_DDR_3WAY_1KB_INTERLEAVING: - case FSL_DDR_3WAY_4KB_INTERLEAVING: - case FSL_DDR_3WAY_8KB_INTERLEAVING: - fsl_ddr_set_intl3r( - info.memctl_opts[0].memctl_interleaving_mode); - break; - default: - break; - } - } - - /* - * Program configuration registers. - * JEDEC specs requires clocks to be stable before deasserting reset - * for RDIMMs. Clocks start after chip select is enabled and clock - * control register is set. During step 1, all controllers have their - * registers set but not enabled. Step 2 proceeds after deasserting - * reset through board FPGA or GPIO. - * For non-registered DIMMs, initialization can go through but it is - * also OK to follow the same flow. - */ - deassert_reset = board_need_mem_reset(); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (info.common_timing_params[i].all_dimms_registered) - deassert_reset = 1; - } - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - debug("Programming controller %u\n", i); - if (info.common_timing_params[i].ndimms_present == 0) { - debug("No dimms present on controller %u; " - "skipping programming\n", i); - continue; - } - /* - * The following call with step = 1 returns before enabling - * the controller. It has to finish with step = 2 later. - */ - fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i, - deassert_reset ? 1 : 0); - } - if (deassert_reset) { - /* Use board FPGA or GPIO to deassert reset signal */ - debug("Deasserting mem reset\n"); - board_deassert_mem_reset(); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - /* Call with step = 2 to continue initialization */ - fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), - i, 2); - } - } - - /* program LAWs */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (info.memctl_opts[i].memctl_interleaving) { - switch (info.memctl_opts[i].memctl_interleaving_mode) { - case FSL_DDR_CACHE_LINE_INTERLEAVING: - case FSL_DDR_PAGE_INTERLEAVING: - case FSL_DDR_BANK_INTERLEAVING: - case FSL_DDR_SUPERBANK_INTERLEAVING: - if (i == 0) { - law_memctl = LAW_TRGT_IF_DDR_INTRLV; - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); - } else if (i == 2) { - law_memctl = LAW_TRGT_IF_DDR_INTLV_34; - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); - } - break; - case FSL_DDR_3WAY_1KB_INTERLEAVING: - case FSL_DDR_3WAY_4KB_INTERLEAVING: - case FSL_DDR_3WAY_8KB_INTERLEAVING: - law_memctl = LAW_TRGT_IF_DDR_INTLV_123; - if (i == 0) { - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); - } - break; - case FSL_DDR_4WAY_1KB_INTERLEAVING: - case FSL_DDR_4WAY_4KB_INTERLEAVING: - case FSL_DDR_4WAY_8KB_INTERLEAVING: - law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; - if (i == 0) - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); - /* place holder for future 4-way interleaving */ - break; - default: - break; - } - } else { - switch (i) { - case 0: - law_memctl = LAW_TRGT_IF_DDR_1; - break; - case 1: - law_memctl = LAW_TRGT_IF_DDR_2; - break; - case 2: - law_memctl = LAW_TRGT_IF_DDR_3; - break; - case 3: - law_memctl = LAW_TRGT_IF_DDR_4; - break; - default: - break; - } - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); - } - } - - debug("total_memory by %s = %llu\n", __func__, total_memory); - -#if !defined(CONFIG_PHYS_64BIT) - /* Check for 4G or more. Bad. */ - if (total_memory >= (1ull << 32)) { - puts("Detected "); - print_size(total_memory, " of memory\n"); - printf(" This U-Boot only supports < 4G of DDR\n"); - printf(" You could rebuild it with CONFIG_PHYS_64BIT\n"); - printf(" "); /* re-align to match init_func_ram print */ - total_memory = CONFIG_MAX_MEM_MAPPED; - } -#endif - - return total_memory; -} - -/* - * fsl_ddr_sdram_size() - This function only returns the size of the total - * memory without setting ddr control registers. - */ -phys_size_t -fsl_ddr_sdram_size(void) -{ - fsl_ddr_info_t info; - unsigned long long total_memory = 0; - - memset(&info, 0 , sizeof(fsl_ddr_info_t)); - - /* Compute it once normally. */ - total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); - - return total_memory; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c deleted file mode 100644 index 1297845553..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include "ddr.h" - -/* - * Use our own stack based buffer before relocation to allow accessing longer - * hwconfig strings that might be in the environment before we've relocated. - * This is pretty fragile on both the use of stack and if the buffer is big - * enough. However we will get a warning from getenv_f for the later. - */ - -/* Board-specific functions defined in each board's ddr.c */ -extern void fsl_ddr_board_options(memctl_options_t *popts, - dimm_params_t *pdimm, - unsigned int ctrl_num); - -struct dynamic_odt { - unsigned int odt_rd_cfg; - unsigned int odt_wr_cfg; - unsigned int odt_rtt_norm; - unsigned int odt_rtt_wr; -}; - -#ifdef CONFIG_FSL_DDR3 -static const struct dynamic_odt single_Q[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS_AND_OTHER_DIMM, - DDR3_RTT_20_OHM, - DDR3_RTT_120_OHM - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, /* tied high */ - DDR3_RTT_OFF, - DDR3_RTT_120_OHM - }, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS_AND_OTHER_DIMM, - DDR3_RTT_20_OHM, - DDR3_RTT_120_OHM - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, /* tied high */ - DDR3_RTT_OFF, - DDR3_RTT_120_OHM - } -}; - -static const struct dynamic_odt single_D[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR3_RTT_OFF, - DDR3_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt single_S[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, -}; - -static const struct dynamic_odt dual_DD[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR3_RTT_30_OHM, - DDR3_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR3_RTT_30_OHM, - DDR3_RTT_OFF - } -}; - -static const struct dynamic_odt dual_DS[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR3_RTT_30_OHM, - DDR3_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_ALL, - DDR3_RTT_20_OHM, - DDR3_RTT_120_OHM - }, - {0, 0, 0, 0} -}; -static const struct dynamic_odt dual_SD[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_ALL, - DDR3_RTT_20_OHM, - DDR3_RTT_120_OHM - }, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR3_RTT_20_OHM, - DDR3_RTT_OFF - } -}; - -static const struct dynamic_odt dual_SS[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_ALL, - DDR3_RTT_30_OHM, - DDR3_RTT_120_OHM - }, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_ALL, - DDR3_RTT_30_OHM, - DDR3_RTT_120_OHM - }, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt dual_D0[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR3_RTT_OFF, - DDR3_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt dual_0D[4] = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_SAME_DIMM, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR3_RTT_OFF, - DDR3_RTT_OFF - } -}; - -static const struct dynamic_odt dual_S0[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - -}; - -static const struct dynamic_odt dual_0S[4] = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_40_OHM, - DDR3_RTT_OFF - }, - {0, 0, 0, 0} - -}; - -static const struct dynamic_odt odt_unknown[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR3_RTT_120_OHM, - DDR3_RTT_OFF - } -}; -#else /* CONFIG_FSL_DDR3 */ -static const struct dynamic_odt single_Q[4] = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt single_D[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt single_S[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, -}; - -static const struct dynamic_odt dual_DD[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - } -}; - -static const struct dynamic_odt dual_DS[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt dual_SD[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - } -}; - -static const struct dynamic_odt dual_SS[4] = { - { /* cs0 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_OTHER_DIMM, - FSL_DDR_ODT_OTHER_DIMM, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt dual_D0[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static const struct dynamic_odt dual_0D[4] = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_ALL, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - } -}; - -static const struct dynamic_odt dual_S0[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - -}; - -static const struct dynamic_odt dual_0S[4] = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR2_RTT_150_OHM, - DDR2_RTT_OFF - }, - {0, 0, 0, 0} - -}; - -static const struct dynamic_odt odt_unknown[4] = { - { /* cs0 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs1 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - }, - { /* cs2 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_CS, - DDR2_RTT_75_OHM, - DDR2_RTT_OFF - }, - { /* cs3 */ - FSL_DDR_ODT_NEVER, - FSL_DDR_ODT_NEVER, - DDR2_RTT_OFF, - DDR2_RTT_OFF - } -}; -#endif - -/* - * Automatically seleect bank interleaving mode based on DIMMs - * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null. - * This function only deal with one or two slots per controller. - */ -static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm) -{ -#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) - if (pdimm[0].n_ranks == 4) - return FSL_DDR_CS0_CS1_CS2_CS3; - else if (pdimm[0].n_ranks == 2) - return FSL_DDR_CS0_CS1; -#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) -#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - if (pdimm[0].n_ranks == 4) - return FSL_DDR_CS0_CS1_CS2_CS3; -#endif - if (pdimm[0].n_ranks == 2) { - if (pdimm[1].n_ranks == 2) - return FSL_DDR_CS0_CS1_CS2_CS3; - else - return FSL_DDR_CS0_CS1; - } -#endif - return 0; -} - -unsigned int populate_memctl_options(int all_dimms_registered, - memctl_options_t *popts, - dimm_params_t *pdimm, - unsigned int ctrl_num) -{ - unsigned int i; - char buffer[HWCONFIG_BUFFER_SIZE]; - char *buf = NULL; -#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2) - const struct dynamic_odt *pdodt = odt_unknown; -#endif - ulong ddr_freq; - - /* - * Extract hwconfig from environment since we have not properly setup - * the environment but need it for ddr config params - */ - if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) - buf = buffer; - -#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2) - /* Chip select options. */ - if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) { - switch (pdimm[0].n_ranks) { - case 1: - pdodt = single_S; - break; - case 2: - pdodt = single_D; - break; - case 4: - pdodt = single_Q; - break; - } - } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) { - switch (pdimm[0].n_ranks) { -#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - case 4: - pdodt = single_Q; - if (pdimm[1].n_ranks) - printf("Error: Quad- and Dual-rank DIMMs " - "cannot be used together\n"); - break; -#endif - case 2: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_DD; - break; - case 1: - pdodt = dual_DS; - break; - case 0: - pdodt = dual_D0; - break; - } - break; - case 1: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_SD; - break; - case 1: - pdodt = dual_SS; - break; - case 0: - pdodt = dual_S0; - break; - } - break; - case 0: - switch (pdimm[1].n_ranks) { - case 2: - pdodt = dual_0D; - break; - case 1: - pdodt = dual_0S; - break; - } - break; - } - } -#endif - - /* Pick chip-select local options. */ - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { -#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2) - popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; - popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; - popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; - popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; -#else - popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER; - popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS; -#endif - popts->cs_local_opts[i].auto_precharge = 0; - } - - /* Pick interleaving mode. */ - - /* - * 0 = no interleaving - * 1 = interleaving between 2 controllers - */ - popts->memctl_interleaving = 0; - - /* - * 0 = cacheline - * 1 = page - * 2 = (logical) bank - * 3 = superbank (only if CS interleaving is enabled) - */ - popts->memctl_interleaving_mode = 0; - - /* - * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl - * 1: page: bit to the left of the column bits selects the memctl - * 2: bank: bit to the left of the bank bits selects the memctl - * 3: superbank: bit to the left of the chip select selects the memctl - * - * NOTE: ba_intlv (rank interleaving) is independent of memory - * controller interleaving; it is only within a memory controller. - * Must use superbank interleaving if rank interleaving is used and - * memory controller interleaving is enabled. - */ - - /* - * 0 = no - * 0x40 = CS0,CS1 - * 0x20 = CS2,CS3 - * 0x60 = CS0,CS1 + CS2,CS3 - * 0x04 = CS0,CS1,CS2,CS3 - */ - popts->ba_intlv_ctl = 0; - - /* Memory Organization Parameters */ - popts->registered_dimm_en = all_dimms_registered; - - /* Operational Mode Paramters */ - - /* Pick ECC modes */ - popts->ecc_mode = 0; /* 0 = disabled, 1 = enabled */ -#ifdef CONFIG_DDR_ECC - if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) { - if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf)) - popts->ecc_mode = 1; - } else - popts->ecc_mode = 1; -#endif - popts->ecc_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */ - - /* - * Choose DQS config - * 0 for DDR1 - * 1 for DDR2 - */ -#if defined(CONFIG_FSL_DDR1) - popts->dqs_config = 0; -#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3) - popts->dqs_config = 1; -#endif - - /* Choose self-refresh during sleep. */ - popts->self_refresh_in_sleep = 1; - - /* Choose dynamic power management mode. */ - popts->dynamic_power = 0; - - /* - * check first dimm for primary sdram width - * presuming all dimms are similar - * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit - */ -#if defined(CONFIG_FSL_DDR1) || defined(CONFIG_FSL_DDR2) - if (pdimm[0].n_ranks != 0) { - if ((pdimm[0].data_width >= 64) && \ - (pdimm[0].data_width <= 72)) - popts->data_bus_width = 0; - else if ((pdimm[0].data_width >= 32) || \ - (pdimm[0].data_width <= 40)) - popts->data_bus_width = 1; - else { - panic("Error: data width %u is invalid!\n", - pdimm[0].data_width); - } - } -#else - if (pdimm[0].n_ranks != 0) { - if (pdimm[0].primary_sdram_width == 64) - popts->data_bus_width = 0; - else if (pdimm[0].primary_sdram_width == 32) - popts->data_bus_width = 1; - else if (pdimm[0].primary_sdram_width == 16) - popts->data_bus_width = 2; - else { - panic("Error: primary sdram width %u is invalid!\n", - pdimm[0].primary_sdram_width); - } - } -#endif - - popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0; - - /* Choose burst length. */ -#if defined(CONFIG_FSL_DDR3) -#if defined(CONFIG_E500MC) - popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */ - popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */ -#else - if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) { - /* 32-bit or 16-bit bus */ - popts->otf_burst_chop_en = 0; - popts->burst_length = DDR_BL8; - } else { - popts->otf_burst_chop_en = 1; /* on-the-fly burst chop */ - popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ - } -#endif -#else - popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */ -#endif - - /* Choose ddr controller address mirror mode */ -#if defined(CONFIG_FSL_DDR3) - popts->mirrored_dimm = pdimm[0].mirrored_dimm; -#endif - - /* Global Timing Parameters. */ - debug("mclk_ps = %u ps\n", get_memory_clk_period_ps()); - - /* Pick a caslat override. */ - popts->cas_latency_override = 0; - popts->cas_latency_override_value = 3; - if (popts->cas_latency_override) { - debug("using caslat override value = %u\n", - popts->cas_latency_override_value); - } - - /* Decide whether to use the computed derated latency */ - popts->use_derated_caslat = 0; - - /* Choose an additive latency. */ - popts->additive_latency_override = 0; - popts->additive_latency_override_value = 3; - if (popts->additive_latency_override) { - debug("using additive latency override value = %u\n", - popts->additive_latency_override_value); - } - - /* - * 2T_EN setting - * - * Factors to consider for 2T_EN: - * - number of DIMMs installed - * - number of components, number of active ranks - * - how much time you want to spend playing around - */ - popts->twot_en = 0; - popts->threet_en = 0; - - /* for RDIMM, address parity enable */ - popts->ap_en = 1; - - /* - * BSTTOPRE precharge interval - * - * Set this to 0 for global auto precharge - * - * FIXME: Should this be configured in picoseconds? - * Why it should be in ps: better understanding of this - * relative to actual DRAM timing parameters such as tRAS. - * e.g. tRAS(min) = 40 ns - */ - popts->bstopre = 0x100; - - /* Minimum CKE pulse width -- tCKE(MIN) */ - popts->tcke_clock_pulse_width_ps - = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR); - - /* - * Window for four activates -- tFAW - * - * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only - * FIXME: varies depending upon number of column addresses or data - * FIXME: width, was considering looking at pdimm->primary_sdram_width - */ -#if defined(CONFIG_FSL_DDR1) - popts->tfaw_window_four_activates_ps = mclk_to_picos(1); - -#elif defined(CONFIG_FSL_DDR2) - /* - * x4/x8; some datasheets have 35000 - * x16 wide columns only? Use 50000? - */ - popts->tfaw_window_four_activates_ps = 37500; - -#elif defined(CONFIG_FSL_DDR3) - popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps; -#endif - popts->zq_en = 0; - popts->wrlvl_en = 0; -#if defined(CONFIG_FSL_DDR3) - /* - * due to ddr3 dimm is fly-by topology - * we suggest to enable write leveling to - * meet the tQDSS under different loading. - */ - popts->wrlvl_en = 1; - popts->zq_en = 1; - popts->wrlvl_override = 0; -#endif - - /* - * Check interleaving configuration from environment. - * Please refer to doc/README.fsl-ddr for the detail. - * - * If memory controller interleaving is enabled, then the data - * bus widths must be programmed identically for all memory controllers. - * - * XXX: Attempt to set all controllers to the same chip select - * interleaving mode. It will do a best effort to get the - * requested ranks interleaved together such that the result - * should be a subset of the requested configuration. - */ -#if (CONFIG_NUM_DDR_CONTROLLERS > 1) - if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) - goto done; - - if (pdimm[0].n_ranks == 0) { - printf("There is no rank on CS0 for controller %d.\n", ctrl_num); - popts->memctl_interleaving = 0; - goto done; - } - popts->memctl_interleaving = 1; - /* - * test null first. if CONFIG_HWCONFIG is not defined - * hwconfig_arg_cmp returns non-zero - */ - if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", - "null", buf)) { - popts->memctl_interleaving = 0; - debug("memory controller interleaving disabled.\n"); - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "cacheline", buf)) { - popts->memctl_interleaving_mode = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : FSL_DDR_CACHE_LINE_INTERLEAVING; - popts->memctl_interleaving = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : 1; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "page", buf)) { - popts->memctl_interleaving_mode = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : FSL_DDR_PAGE_INTERLEAVING; - popts->memctl_interleaving = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : 1; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "bank", buf)) { - popts->memctl_interleaving_mode = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : FSL_DDR_BANK_INTERLEAVING; - popts->memctl_interleaving = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : 1; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "superbank", buf)) { - popts->memctl_interleaving_mode = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : FSL_DDR_SUPERBANK_INTERLEAVING; - popts->memctl_interleaving = - ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? - 0 : 1; -#if (CONFIG_NUM_DDR_CONTROLLERS == 3) - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "3way_1KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_3WAY_1KB_INTERLEAVING; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "3way_4KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_3WAY_4KB_INTERLEAVING; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "3way_8KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_3WAY_8KB_INTERLEAVING; -#elif (CONFIG_NUM_DDR_CONTROLLERS == 4) - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "4way_1KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_4WAY_1KB_INTERLEAVING; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "4way_4KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_4WAY_4KB_INTERLEAVING; - } else if (hwconfig_subarg_cmp_f("fsl_ddr", - "ctlr_intlv", - "4way_8KB", buf)) { - popts->memctl_interleaving_mode = - FSL_DDR_4WAY_8KB_INTERLEAVING; -#endif - } else { - popts->memctl_interleaving = 0; - printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); - } -done: -#endif - if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && - (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { - /* test null first. if CONFIG_HWCONFIG is not defined, - * hwconfig_subarg_cmp_f returns non-zero */ - if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "null", buf)) - debug("bank interleaving disabled.\n"); - else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "cs0_cs1", buf)) - popts->ba_intlv_ctl = FSL_DDR_CS0_CS1; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "cs2_cs3", buf)) - popts->ba_intlv_ctl = FSL_DDR_CS2_CS3; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "cs0_cs1_and_cs2_cs3", buf)) - popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "cs0_cs1_cs2_cs3", buf)) - popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", - "auto", buf)) - popts->ba_intlv_ctl = auto_bank_intlv(pdimm); - else - printf("hwconfig has unrecognized parameter for bank_intlv.\n"); - switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { - case FSL_DDR_CS0_CS1_CS2_CS3: -#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) - if (pdimm[0].n_ranks < 4) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(chip-select) for " - "CS0+CS1+CS2+CS3 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } -#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) -#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE - if (pdimm[0].n_ranks == 4) - break; -#endif - if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(chip-select) for " - "CS0+CS1+CS2+CS3 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } - if (pdimm[0].capacity != pdimm[1].capacity) { - popts->ba_intlv_ctl = 0; - printf("Not identical DIMM size for " - "CS0+CS1+CS2+CS3 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } -#endif - break; - case FSL_DDR_CS0_CS1: - if (pdimm[0].n_ranks < 2) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(chip-select) for " - "CS0+CS1 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } - break; - case FSL_DDR_CS2_CS3: -#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) - if (pdimm[0].n_ranks < 4) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(chip-select) for CS2+CS3 " - "on controller %d, interleaving disabled!\n", ctrl_num); - } -#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) - if (pdimm[1].n_ranks < 2) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(chip-select) for CS2+CS3 " - "on controller %d, interleaving disabled!\n", ctrl_num); - } -#endif - break; - case FSL_DDR_CS0_CS1_AND_CS2_CS3: -#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) - if (pdimm[0].n_ranks < 4) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(CS) for CS0+CS1 and " - "CS2+CS3 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } -#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) - if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) { - popts->ba_intlv_ctl = 0; - printf("Not enough bank(CS) for CS0+CS1 and " - "CS2+CS3 on controller %d, " - "interleaving disabled!\n", ctrl_num); - } -#endif - break; - default: - popts->ba_intlv_ctl = 0; - break; - } - } - - if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) { - if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf)) - popts->addr_hash = 0; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", - "true", buf)) - popts->addr_hash = 1; - } - - if (pdimm[0].n_ranks == 4) - popts->quad_rank_present = 1; - - ddr_freq = get_ddr_freq(0) / 1000000; - if (popts->registered_dimm_en) { - popts->rcw_override = 1; - popts->rcw_1 = 0x000a5a00; - if (ddr_freq <= 800) - popts->rcw_2 = 0x00000000; - else if (ddr_freq <= 1066) - popts->rcw_2 = 0x00100000; - else if (ddr_freq <= 1333) - popts->rcw_2 = 0x00200000; - else - popts->rcw_2 = 0x00300000; - } - - fsl_ddr_board_options(popts, pdimm, ctrl_num); - - return 0; -} - -void check_interleaving_options(fsl_ddr_info_t *pinfo) -{ - int i, j, k, check_n_ranks, intlv_invalid = 0; - unsigned int check_intlv, check_n_row_addr, check_n_col_addr; - unsigned long long check_rank_density; - struct dimm_params_s *dimm; - /* - * Check if all controllers are configured for memory - * controller interleaving. Identical dimms are recommended. At least - * the size, row and col address should be checked. - */ - j = 0; - check_n_ranks = pinfo->dimm_params[0][0].n_ranks; - check_rank_density = pinfo->dimm_params[0][0].rank_density; - check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; - check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; - check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - dimm = &pinfo->dimm_params[i][0]; - if (!pinfo->memctl_opts[i].memctl_interleaving) { - continue; - } else if (((check_rank_density != dimm->rank_density) || - (check_n_ranks != dimm->n_ranks) || - (check_n_row_addr != dimm->n_row_addr) || - (check_n_col_addr != dimm->n_col_addr) || - (check_intlv != - pinfo->memctl_opts[i].memctl_interleaving_mode))){ - intlv_invalid = 1; - break; - } else { - j++; - } - - } - if (intlv_invalid) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - pinfo->memctl_opts[i].memctl_interleaving = 0; - printf("Not all DIMMs are identical. " - "Memory controller interleaving disabled.\n"); - } else { - switch (check_intlv) { - case FSL_DDR_CACHE_LINE_INTERLEAVING: - case FSL_DDR_PAGE_INTERLEAVING: - case FSL_DDR_BANK_INTERLEAVING: - case FSL_DDR_SUPERBANK_INTERLEAVING: - if (3 == CONFIG_NUM_DDR_CONTROLLERS) - k = 2; - else - k = CONFIG_NUM_DDR_CONTROLLERS; - break; - case FSL_DDR_3WAY_1KB_INTERLEAVING: - case FSL_DDR_3WAY_4KB_INTERLEAVING: - case FSL_DDR_3WAY_8KB_INTERLEAVING: - case FSL_DDR_4WAY_1KB_INTERLEAVING: - case FSL_DDR_4WAY_4KB_INTERLEAVING: - case FSL_DDR_4WAY_8KB_INTERLEAVING: - default: - k = CONFIG_NUM_DDR_CONTROLLERS; - break; - } - debug("%d of %d controllers are interleaving.\n", j, k); - if (j && (j != k)) { - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) - pinfo->memctl_opts[i].memctl_interleaving = 0; - printf("Not all controllers have compatible " - "interleaving mode. All disabled.\n"); - } - } - debug("Checking interleaving options completed\n"); -} - -int fsl_use_spd(void) -{ - int use_spd = 0; - -#ifdef CONFIG_DDR_SPD - char buffer[HWCONFIG_BUFFER_SIZE]; - char *buf = NULL; - - /* - * Extract hwconfig from environment since we have not properly setup - * the environment but need it for ddr config params - */ - if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) - buf = buffer; - - /* if hwconfig is not enabled, or "sdram" is not defined, use spd */ - if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) { - if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf)) - use_spd = 1; - else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", - "fixed", buf)) - use_spd = 0; - else - use_spd = 1; - } else - use_spd = 1; -#endif - - return use_spd; -} diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c deleted file mode 100644 index acfe1f095f..0000000000 --- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "ddr.h" - -/* To avoid 64-bit full-divides, we factor this here */ -#define ULL_2E12 2000000000000ULL -#define UL_5POW12 244140625UL -#define UL_2POW13 (1UL << 13) - -#define ULL_8FS 0xFFFFFFFFULL - -/* - * Round up mclk_ps to nearest 1 ps in memory controller code - * if the error is 0.5ps or more. - * - * If an imprecise data rate is too high due to rounding error - * propagation, compute a suitably rounded mclk_ps to compute - * a working memory controller configuration. - */ -unsigned int get_memory_clk_period_ps(void) -{ - unsigned int data_rate = get_ddr_freq(0); - unsigned int result; - - /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ - unsigned long long rem, mclk_ps = ULL_2E12; - - /* Now perform the big divide, the result fits in 32-bits */ - rem = do_div(mclk_ps, data_rate); - result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; - - return result; -} - -/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */ -unsigned int picos_to_mclk(unsigned int picos) -{ - unsigned long long clks, clks_rem; - unsigned long data_rate = get_ddr_freq(0); - - /* Short circuit for zero picos */ - if (!picos) - return 0; - - /* First multiply the time by the data rate (32x32 => 64) */ - clks = picos * (unsigned long long)data_rate; - /* - * Now divide by 5^12 and track the 32-bit remainder, then divide - * by 2*(2^12) using shifts (and updating the remainder). - */ - clks_rem = do_div(clks, UL_5POW12); - clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12; - clks >>= 13; - - /* If we had a remainder greater than the 1ps error, then round up */ - if (clks_rem > data_rate) - clks++; - - /* Clamp to the maximum representable value */ - if (clks > ULL_8FS) - clks = ULL_8FS; - return (unsigned int) clks; -} - -unsigned int mclk_to_picos(unsigned int mclk) -{ - return get_memory_clk_period_ps() * mclk; -} - -void -__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, - unsigned int law_memctl, - unsigned int ctrl_num) -{ - unsigned long long base = memctl_common_params->base_address; - unsigned long long size = memctl_common_params->total_mem; - - /* - * If no DIMMs on this controller, do not proceed any further. - */ - if (!memctl_common_params->ndimms_present) { - return; - } - -#if !defined(CONFIG_PHYS_64BIT) - if (base >= CONFIG_MAX_MEM_MAPPED) - return; - if ((base + size) >= CONFIG_MAX_MEM_MAPPED) - size = CONFIG_MAX_MEM_MAPPED - base; -#endif - if (set_ddr_laws(base, size, law_memctl) < 0) { - printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num, - law_memctl); - return ; - } - debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n", - base, size, law_memctl); -} - -__attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void -fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, - unsigned int memctl_interleaved, - unsigned int ctrl_num); - -void fsl_ddr_set_intl3r(const unsigned int granule_size) -{ -#ifdef CONFIG_E6500 - u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); - *mcintl3r = 0x80000000 | (granule_size & 0x1f); - debug("Enable MCINTL3R with granule size 0x%x\n", granule_size); -#endif -} - -u32 fsl_ddr_get_intl3r(void) -{ - u32 val = 0; -#ifdef CONFIG_E6500 - u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); - val = *mcintl3r; -#endif - return val; -} - -void board_add_ram_info(int use_default) -{ - ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); - -#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3) - u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); -#endif -#if (CONFIG_NUM_DDR_CONTROLLERS > 1) - uint32_t cs0_config = in_be32(&ddr->cs0_config); -#endif - uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg); - int cas_lat; - -#if CONFIG_NUM_DDR_CONTROLLERS >= 2 - if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { - ddr = (void __iomem *)CONFIG_SYS_MPC8xxx_DDR2_ADDR; - sdram_cfg = in_be32(&ddr->sdram_cfg); - } -#endif -#if CONFIG_NUM_DDR_CONTROLLERS >= 3 - if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { - ddr = (void __iomem *)CONFIG_SYS_MPC8xxx_DDR3_ADDR; - sdram_cfg = in_be32(&ddr->sdram_cfg); - } -#endif - puts(" (DDR"); - switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> - SDRAM_CFG_SDRAM_TYPE_SHIFT) { - case SDRAM_TYPE_DDR1: - puts("1"); - break; - case SDRAM_TYPE_DDR2: - puts("2"); - break; - case SDRAM_TYPE_DDR3: - puts("3"); - break; - default: - puts("?"); - break; - } - - if (sdram_cfg & SDRAM_CFG_32_BE) - puts(", 32-bit"); - else if (sdram_cfg & SDRAM_CFG_16_BE) - puts(", 16-bit"); - else - puts(", 64-bit"); - - /* Calculate CAS latency based on timing cfg values */ - cas_lat = ((in_be32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1; - if ((in_be32(&ddr->timing_cfg_3) >> 12) & 1) - cas_lat += (8 << 1); - printf(", CL=%d", cas_lat >> 1); - if (cas_lat & 0x1) - puts(".5"); - - if (sdram_cfg & SDRAM_CFG_ECC_EN) - puts(", ECC on)"); - else - puts(", ECC off)"); - -#if (CONFIG_NUM_DDR_CONTROLLERS == 3) -#ifdef CONFIG_E6500 - if (*mcintl3r & 0x80000000) { - puts("\n"); - puts(" DDR Controller Interleaving Mode: "); - switch (*mcintl3r & 0x1f) { - case FSL_DDR_3WAY_1KB_INTERLEAVING: - puts("3-way 1KB"); - break; - case FSL_DDR_3WAY_4KB_INTERLEAVING: - puts("3-way 4KB"); - break; - case FSL_DDR_3WAY_8KB_INTERLEAVING: - puts("3-way 8KB"); - break; - default: - puts("3-way UNKNOWN"); - break; - } - } -#endif -#endif -#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) - if (cs0_config & 0x20000000) { - puts("\n"); - puts(" DDR Controller Interleaving Mode: "); - - switch ((cs0_config >> 24) & 0xf) { - case FSL_DDR_CACHE_LINE_INTERLEAVING: - puts("cache line"); - break; - case FSL_DDR_PAGE_INTERLEAVING: - puts("page"); - break; - case FSL_DDR_BANK_INTERLEAVING: - puts("bank"); - break; - case FSL_DDR_SUPERBANK_INTERLEAVING: - puts("super-bank"); - break; - default: - puts("invalid"); - break; - } - } -#endif - - if ((sdram_cfg >> 8) & 0x7f) { - puts("\n"); - puts(" DDR Chip-Select Interleaving Mode: "); - switch(sdram_cfg >> 8 & 0x7f) { - case FSL_DDR_CS0_CS1_CS2_CS3: - puts("CS0+CS1+CS2+CS3"); - break; - case FSL_DDR_CS0_CS1: - puts("CS0+CS1"); - break; - case FSL_DDR_CS2_CS3: - puts("CS2+CS3"); - break; - case FSL_DDR_CS0_CS1_AND_CS2_CS3: - puts("CS0+CS1 and CS2+CS3"); - break; - default: - puts("invalid"); - break; - } - } -} diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h index 3c17c99146..423a6fb8dc 100644 --- a/arch/powerpc/include/asm/config.h +++ b/arch/powerpc/include/asm/config.h @@ -9,10 +9,16 @@ #ifdef CONFIG_MPC85xx #include +#define CONFIG_SYS_FSL_DDR #endif #ifdef CONFIG_MPC86xx #include +#define CONFIG_SYS_FSL_DDR +#endif + +#ifdef CONFIG_MPC83xx +#define CONFIG_SYS_FSL_DDR #endif #ifndef HWCONFIG_BUFFER_SIZE diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index d4cd27dd00..047fdf1d8c 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -40,17 +40,20 @@ #elif defined(CONFIG_MPC8540) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 8 +#define CONFIG_SYS_FSL_DDRC_GEN1 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 #elif defined(CONFIG_MPC8541) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 8 +#define CONFIG_SYS_FSL_DDRC_GEN1 #define CONFIG_SYS_FSL_SEC_COMPAT 2 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 #elif defined(CONFIG_MPC8544) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 10 +#define CONFIG_SYS_FSL_DDRC_GEN2 #define CONFIG_SYS_PPC_E500_DEBUG_TLB 0 #define CONFIG_SYS_FSL_SEC_COMPAT 2 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 @@ -59,6 +62,7 @@ #elif defined(CONFIG_MPC8548) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 10 +#define CONFIG_SYS_FSL_DDRC_GEN2 #define CONFIG_SYS_PPC_E500_DEBUG_TLB 0 #define CONFIG_SYS_FSL_SEC_COMPAT 2 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 @@ -77,17 +81,20 @@ #elif defined(CONFIG_MPC8555) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 8 +#define CONFIG_SYS_FSL_DDRC_GEN1 #define CONFIG_SYS_FSL_SEC_COMPAT 2 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 #elif defined(CONFIG_MPC8560) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 8 +#define CONFIG_SYS_FSL_DDRC_GEN1 #define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000 #elif defined(CONFIG_MPC8568) #define CONFIG_MAX_CPUS 1 #define CONFIG_SYS_FSL_NUM_LAWS 10 +#define CONFIG_SYS_FSL_DDRC_GEN2 #define CONFIG_SYS_FSL_SEC_COMPAT 2 #define QE_MURAM_SIZE 0x10000UL #define MAX_QE_RISC 2 @@ -738,4 +745,10 @@ defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022) #define CONFIG_SYS_FSL_THREADS_PER_CORE 1 #endif +#if !defined(CONFIG_SYS_FSL_DDRC_GEN1) && \ + !defined(CONFIG_SYS_FSL_DDRC_GEN2) && \ + !defined(CONFIG_SYS_FSL_DDRC_GEN3) +#define CONFIG_SYS_FSL_DDRC_GEN3 +#endif + #endif /* _ASM_MPC85xx_CONFIG_H_ */ diff --git a/arch/powerpc/include/asm/config_mpc86xx.h b/arch/powerpc/include/asm/config_mpc86xx.h index 694b110302..4f9b2252be 100644 --- a/arch/powerpc/include/asm/config_mpc86xx.h +++ b/arch/powerpc/include/asm/config_mpc86xx.h @@ -7,6 +7,8 @@ #ifndef _ASM_MPC86xx_CONFIG_H_ #define _ASM_MPC86xx_CONFIG_H_ +#define CONFIG_SYS_FSL_DDR_86XX + /* SoC specific defines for Freescale MPC86xx processors */ #if defined(CONFIG_MPC8610) diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h deleted file mode 100644 index 99a72bc6e1..0000000000 --- a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#ifndef DDR2_DIMM_PARAMS_H -#define DDR2_DIMM_PARAMS_H - -#define EDC_DATA_PARITY 1 -#define EDC_ECC 2 -#define EDC_AC_PARITY 4 - -/* Parameters for a DDR2 dimm computed from the SPD */ -typedef struct dimm_params_s { - - /* DIMM organization parameters */ - char mpart[19]; /* guaranteed null terminated */ - - unsigned int n_ranks; - unsigned long long rank_density; - unsigned long long capacity; - unsigned int data_width; - unsigned int primary_sdram_width; - unsigned int ec_sdram_width; - unsigned int registered_dimm; - unsigned int device_width; /* x4, x8, x16 components */ - - /* SDRAM device parameters */ - unsigned int n_row_addr; - unsigned int n_col_addr; - unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */ - unsigned int n_banks_per_sdram_device; - unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */ - unsigned int row_density; - - /* used in computing base address of DIMMs */ - unsigned long long base_address; - /* mirrored DIMMs */ - unsigned int mirrored_dimm; /* only for ddr3 */ - - /* DIMM timing parameters */ - - unsigned int mtb_ps; /* medium timebase ps, only for ddr3 */ - unsigned int ftb_10th_ps; /* fine timebase, in 1/10 ps, only for ddr3 */ - unsigned int taa_ps; /* minimum CAS latency time, only for ddr3 */ - unsigned int tfaw_ps; /* four active window delay, only for ddr3 */ - - /* - * SDRAM clock periods - * The range for these are 1000-10000 so a short should be sufficient - */ - unsigned int tckmin_x_ps; - unsigned int tckmin_x_minus_1_ps; - unsigned int tckmin_x_minus_2_ps; - unsigned int tckmax_ps; - - /* SPD-defined CAS latencies */ - unsigned int caslat_x; - unsigned int caslat_x_minus_1; - unsigned int caslat_x_minus_2; - - unsigned int caslat_lowest_derated; /* Derated CAS latency */ - - /* basic timing parameters */ - unsigned int trcd_ps; - unsigned int trp_ps; - unsigned int tras_ps; - - unsigned int twr_ps; /* maximum = 63750 ps */ - unsigned int twtr_ps; /* maximum = 63750 ps */ - unsigned int trfc_ps; /* max = 255 ns + 256 ns + .75 ns - = 511750 ps */ - - unsigned int trrd_ps; /* maximum = 63750 ps */ - unsigned int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ - - unsigned int refresh_rate_ps; - unsigned int extended_op_srt; - - /* DDR3 doesn't need these as below */ - unsigned int tis_ps; /* byte 32, spd->ca_setup */ - unsigned int tih_ps; /* byte 33, spd->ca_hold */ - unsigned int tds_ps; /* byte 34, spd->data_setup */ - unsigned int tdh_ps; /* byte 35, spd->data_hold */ - unsigned int trtp_ps; /* byte 38, spd->trtp */ - unsigned int tdqsq_max_ps; /* byte 44, spd->tdqsq */ - unsigned int tqhs_ps; /* byte 45, spd->tqhs */ - - /* DDR3 RDIMM */ - unsigned char rcw[16]; /* Register Control Word 0-15 */ -} dimm_params_t; - -extern unsigned int ddr_compute_dimm_parameters( - const generic_spd_eeprom_t *spd, - dimm_params_t *pdimm, - unsigned int dimm_number); - -#endif diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h deleted file mode 100644 index 2c3c514ba3..0000000000 --- a/arch/powerpc/include/asm/fsl_ddr_sdram.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright 2008-2011 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - */ - -#ifndef FSL_DDR_MEMCTL_H -#define FSL_DDR_MEMCTL_H - -/* - * Pick a basic DDR Technology. - */ -#include - -#define SDRAM_TYPE_DDR1 2 -#define SDRAM_TYPE_DDR2 3 -#define SDRAM_TYPE_LPDDR1 6 -#define SDRAM_TYPE_DDR3 7 - -#define DDR_BL4 4 /* burst length 4 */ -#define DDR_BC4 DDR_BL4 /* burst chop for ddr3 */ -#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */ -#define DDR_BL8 8 /* burst length 8 */ - -#define DDR3_RTT_OFF 0 -#define DDR3_RTT_60_OHM 1 /* RTT_Nom = RZQ/4 */ -#define DDR3_RTT_120_OHM 2 /* RTT_Nom = RZQ/2 */ -#define DDR3_RTT_40_OHM 3 /* RTT_Nom = RZQ/6 */ -#define DDR3_RTT_20_OHM 4 /* RTT_Nom = RZQ/12 */ -#define DDR3_RTT_30_OHM 5 /* RTT_Nom = RZQ/8 */ - -#define DDR2_RTT_OFF 0 -#define DDR2_RTT_75_OHM 1 -#define DDR2_RTT_150_OHM 2 -#define DDR2_RTT_50_OHM 3 - -#if defined(CONFIG_FSL_DDR1) -#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (1) -typedef ddr1_spd_eeprom_t generic_spd_eeprom_t; -#ifndef CONFIG_FSL_SDRAM_TYPE -#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR1 -#endif -#elif defined(CONFIG_FSL_DDR2) -#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) -typedef ddr2_spd_eeprom_t generic_spd_eeprom_t; -#ifndef CONFIG_FSL_SDRAM_TYPE -#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR2 -#endif -#elif defined(CONFIG_FSL_DDR3) -#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) /* FIXME */ -typedef ddr3_spd_eeprom_t generic_spd_eeprom_t; -#ifndef CONFIG_FSL_SDRAM_TYPE -#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR3 -#endif -#endif /* #if defined(CONFIG_FSL_DDR1) */ - -#define FSL_DDR_ODT_NEVER 0x0 -#define FSL_DDR_ODT_CS 0x1 -#define FSL_DDR_ODT_ALL_OTHER_CS 0x2 -#define FSL_DDR_ODT_OTHER_DIMM 0x3 -#define FSL_DDR_ODT_ALL 0x4 -#define FSL_DDR_ODT_SAME_DIMM 0x5 -#define FSL_DDR_ODT_CS_AND_OTHER_DIMM 0x6 -#define FSL_DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7 - -/* define bank(chip select) interleaving mode */ -#define FSL_DDR_CS0_CS1 0x40 -#define FSL_DDR_CS2_CS3 0x20 -#define FSL_DDR_CS0_CS1_AND_CS2_CS3 (FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3) -#define FSL_DDR_CS0_CS1_CS2_CS3 (FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04) - -/* define memory controller interleaving mode */ -#define FSL_DDR_CACHE_LINE_INTERLEAVING 0x0 -#define FSL_DDR_PAGE_INTERLEAVING 0x1 -#define FSL_DDR_BANK_INTERLEAVING 0x2 -#define FSL_DDR_SUPERBANK_INTERLEAVING 0x3 -#define FSL_DDR_3WAY_1KB_INTERLEAVING 0xA -#define FSL_DDR_3WAY_4KB_INTERLEAVING 0xC -#define FSL_DDR_3WAY_8KB_INTERLEAVING 0xD -/* placeholder for 4-way interleaving */ -#define FSL_DDR_4WAY_1KB_INTERLEAVING 0x1A -#define FSL_DDR_4WAY_4KB_INTERLEAVING 0x1C -#define FSL_DDR_4WAY_8KB_INTERLEAVING 0x1D - -#define SDRAM_CS_CONFIG_EN 0x80000000 - -/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration - */ -#define SDRAM_CFG_MEM_EN 0x80000000 -#define SDRAM_CFG_SREN 0x40000000 -#define SDRAM_CFG_ECC_EN 0x20000000 -#define SDRAM_CFG_RD_EN 0x10000000 -#define SDRAM_CFG_SDRAM_TYPE_DDR1 0x02000000 -#define SDRAM_CFG_SDRAM_TYPE_DDR2 0x03000000 -#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000 -#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24 -#define SDRAM_CFG_DYN_PWR 0x00200000 -#define SDRAM_CFG_DBW_MASK 0x00180000 -#define SDRAM_CFG_DBW_SHIFT 19 -#define SDRAM_CFG_32_BE 0x00080000 -#define SDRAM_CFG_16_BE 0x00100000 -#define SDRAM_CFG_8_BE 0x00040000 -#define SDRAM_CFG_NCAP 0x00020000 -#define SDRAM_CFG_2T_EN 0x00008000 -#define SDRAM_CFG_BI 0x00000001 - -#define SDRAM_CFG2_D_INIT 0x00000010 -#define SDRAM_CFG2_ODT_CFG_MASK 0x00600000 -#define SDRAM_CFG2_ODT_NEVER 0 -#define SDRAM_CFG2_ODT_ONLY_WRITE 1 -#define SDRAM_CFG2_ODT_ONLY_READ 2 -#define SDRAM_CFG2_ODT_ALWAYS 3 - -#define TIMING_CFG_2_CPO_MASK 0x0F800000 - -#if defined(CONFIG_P4080) -#define RD_TO_PRE_MASK 0xf -#define RD_TO_PRE_SHIFT 13 -#define WR_DATA_DELAY_MASK 0xf -#define WR_DATA_DELAY_SHIFT 9 -#else -#define RD_TO_PRE_MASK 0x7 -#define RD_TO_PRE_SHIFT 13 -#define WR_DATA_DELAY_MASK 0x7 -#define WR_DATA_DELAY_SHIFT 10 -#endif - -/* DDR_MD_CNTL */ -#define MD_CNTL_MD_EN 0x80000000 -#define MD_CNTL_CS_SEL_CS0 0x00000000 -#define MD_CNTL_CS_SEL_CS1 0x10000000 -#define MD_CNTL_CS_SEL_CS2 0x20000000 -#define MD_CNTL_CS_SEL_CS3 0x30000000 -#define MD_CNTL_CS_SEL_CS0_CS1 0x40000000 -#define MD_CNTL_CS_SEL_CS2_CS3 0x50000000 -#define MD_CNTL_MD_SEL_MR 0x00000000 -#define MD_CNTL_MD_SEL_EMR 0x01000000 -#define MD_CNTL_MD_SEL_EMR2 0x02000000 -#define MD_CNTL_MD_SEL_EMR3 0x03000000 -#define MD_CNTL_SET_REF 0x00800000 -#define MD_CNTL_SET_PRE 0x00400000 -#define MD_CNTL_CKE_CNTL_LOW 0x00100000 -#define MD_CNTL_CKE_CNTL_HIGH 0x00200000 -#define MD_CNTL_WRCW 0x00080000 -#define MD_CNTL_MD_VALUE(x) (x & 0x0000FFFF) - -/* DDR_CDR1 */ -#define DDR_CDR1_DHC_EN 0x80000000 -#define DDR_CDR1_ODT_SHIFT 17 -#define DDR_CDR1_ODT_MASK 0x6 -#define DDR_CDR2_ODT_MASK 0x1 -#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT) -#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK) - -#if (defined(CONFIG_SYS_FSL_DDR_VER) && \ - (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)) -#define DDR_CDR_ODT_OFF 0x0 -#define DDR_CDR_ODT_120ohm 0x1 -#define DDR_CDR_ODT_180ohm 0x2 -#define DDR_CDR_ODT_75ohm 0x3 -#define DDR_CDR_ODT_110ohm 0x4 -#define DDR_CDR_ODT_60hm 0x5 -#define DDR_CDR_ODT_70ohm 0x6 -#define DDR_CDR_ODT_47ohm 0x7 -#else -#define DDR_CDR_ODT_75ohm 0x0 -#define DDR_CDR_ODT_55ohm 0x1 -#define DDR_CDR_ODT_60ohm 0x2 -#define DDR_CDR_ODT_50ohm 0x3 -#define DDR_CDR_ODT_150ohm 0x4 -#define DDR_CDR_ODT_43ohm 0x5 -#define DDR_CDR_ODT_120ohm 0x6 -#endif - -/* Record of register values computed */ -typedef struct fsl_ddr_cfg_regs_s { - struct { - unsigned int bnds; - unsigned int config; - unsigned int config_2; - } cs[CONFIG_CHIP_SELECTS_PER_CTRL]; - unsigned int timing_cfg_3; - unsigned int timing_cfg_0; - unsigned int timing_cfg_1; - unsigned int timing_cfg_2; - unsigned int ddr_sdram_cfg; - unsigned int ddr_sdram_cfg_2; - unsigned int ddr_sdram_mode; - unsigned int ddr_sdram_mode_2; - unsigned int ddr_sdram_mode_3; - unsigned int ddr_sdram_mode_4; - unsigned int ddr_sdram_mode_5; - unsigned int ddr_sdram_mode_6; - unsigned int ddr_sdram_mode_7; - unsigned int ddr_sdram_mode_8; - unsigned int ddr_sdram_md_cntl; - unsigned int ddr_sdram_interval; - unsigned int ddr_data_init; - unsigned int ddr_sdram_clk_cntl; - unsigned int ddr_init_addr; - unsigned int ddr_init_ext_addr; - unsigned int timing_cfg_4; - unsigned int timing_cfg_5; - unsigned int ddr_zq_cntl; - unsigned int ddr_wrlvl_cntl; - unsigned int ddr_wrlvl_cntl_2; - unsigned int ddr_wrlvl_cntl_3; - unsigned int ddr_sr_cntr; - unsigned int ddr_sdram_rcw_1; - unsigned int ddr_sdram_rcw_2; - unsigned int ddr_eor; - unsigned int ddr_cdr1; - unsigned int ddr_cdr2; - unsigned int err_disable; - unsigned int err_int_en; - unsigned int debug[32]; -} fsl_ddr_cfg_regs_t; - -typedef struct memctl_options_partial_s { - unsigned int all_dimms_ecc_capable; - unsigned int all_dimms_tckmax_ps; - unsigned int all_dimms_burst_lengths_bitmask; - unsigned int all_dimms_registered; - unsigned int all_dimms_unbuffered; - /* unsigned int lowest_common_SPD_caslat; */ - unsigned int all_dimms_minimum_trcd_ps; -} memctl_options_partial_t; - -#define DDR_DATA_BUS_WIDTH_64 0 -#define DDR_DATA_BUS_WIDTH_32 1 -#define DDR_DATA_BUS_WIDTH_16 2 -/* - * Generalized parameters for memory controller configuration, - * might be a little specific to the FSL memory controller - */ -typedef struct memctl_options_s { - /* - * Memory organization parameters - * - * if DIMM is present in the system - * where DIMMs are with respect to chip select - * where chip selects are with respect to memory boundaries - */ - unsigned int registered_dimm_en; /* use registered DIMM support */ - - /* Options local to a Chip Select */ - struct cs_local_opts_s { - unsigned int auto_precharge; - unsigned int odt_rd_cfg; - unsigned int odt_wr_cfg; - unsigned int odt_rtt_norm; - unsigned int odt_rtt_wr; - } cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL]; - - /* Special configurations for chip select */ - unsigned int memctl_interleaving; - unsigned int memctl_interleaving_mode; - unsigned int ba_intlv_ctl; - unsigned int addr_hash; - - /* Operational mode parameters */ - unsigned int ecc_mode; /* Use ECC? */ - /* Initialize ECC using memory controller? */ - unsigned int ecc_init_using_memctl; - unsigned int dqs_config; /* Use DQS? maybe only with DDR2? */ - /* SREN - self-refresh during sleep */ - unsigned int self_refresh_in_sleep; - unsigned int dynamic_power; /* DYN_PWR */ - /* memory data width to use (16-bit, 32-bit, 64-bit) */ - unsigned int data_bus_width; - unsigned int burst_length; /* BL4, OTF and BL8 */ - /* On-The-Fly Burst Chop enable */ - unsigned int otf_burst_chop_en; - /* mirrior DIMMs for DDR3 */ - unsigned int mirrored_dimm; - unsigned int quad_rank_present; - unsigned int ap_en; /* address parity enable for RDIMM */ - unsigned int x4_en; /* enable x4 devices */ - - /* Global Timing Parameters */ - unsigned int cas_latency_override; - unsigned int cas_latency_override_value; - unsigned int use_derated_caslat; - unsigned int additive_latency_override; - unsigned int additive_latency_override_value; - - unsigned int clk_adjust; /* */ - unsigned int cpo_override; - unsigned int write_data_delay; /* DQS adjust */ - - unsigned int wrlvl_override; - unsigned int wrlvl_sample; /* Write leveling */ - unsigned int wrlvl_start; - unsigned int wrlvl_ctl_2; - unsigned int wrlvl_ctl_3; - - unsigned int half_strength_driver_enable; - unsigned int twot_en; - unsigned int threet_en; - unsigned int bstopre; - unsigned int tcke_clock_pulse_width_ps; /* tCKE */ - unsigned int tfaw_window_four_activates_ps; /* tFAW -- FOUR_ACT */ - - /* Rtt impedance */ - unsigned int rtt_override; /* rtt_override enable */ - unsigned int rtt_override_value; /* that is Rtt_Nom for DDR3 */ - unsigned int rtt_wr_override_value; /* this is Rtt_WR for DDR3 */ - - /* Automatic self refresh */ - unsigned int auto_self_refresh_en; - unsigned int sr_it; - /* ZQ calibration */ - unsigned int zq_en; - /* Write leveling */ - unsigned int wrlvl_en; - /* RCW override for RDIMM */ - unsigned int rcw_override; - unsigned int rcw_1; - unsigned int rcw_2; - /* control register 1 */ - unsigned int ddr_cdr1; - unsigned int ddr_cdr2; - - unsigned int trwt_override; - unsigned int trwt; /* read-to-write turnaround */ -} memctl_options_t; - -extern phys_size_t fsl_ddr_sdram(void); -extern phys_size_t fsl_ddr_sdram_size(void); -extern int fsl_use_spd(void); -extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step); -u32 fsl_ddr_get_intl3r(void); - -static void __board_assert_mem_reset(void) -{ -} - -static void __board_deassert_mem_reset(void) -{ -} - -void board_assert_mem_reset(void) - __attribute__((weak, alias("__board_assert_mem_reset"))); - -void board_deassert_mem_reset(void) - __attribute__((weak, alias("__board_deassert_mem_reset"))); - -static int __board_need_mem_reset(void) -{ - return 0; -} - -int board_need_mem_reset(void) - __attribute__((weak, alias("__board_need_mem_reset"))); - -/* - * The 85xx boards have a common prototype for fixed_sdram so put the - * declaration here. - */ -#ifdef CONFIG_MPC85xx -extern phys_size_t fixed_sdram(void); -#endif - -#if defined(CONFIG_DDR_ECC) -extern void ddr_enable_ecc(unsigned int dram_size); -#endif - - -typedef struct fixed_ddr_parm{ - int min_freq; - int max_freq; - fsl_ddr_cfg_regs_t *ddr_settings; -} fixed_ddr_parm_t; -#endif diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h index 289f7cac52..1042b0c308 100644 --- a/arch/powerpc/include/asm/immap_83xx.h +++ b/arch/powerpc/include/asm/immap_83xx.h @@ -279,7 +279,7 @@ typedef struct qesba83xx { /* * DDR Memory Controller Memory Map */ -#if defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3) typedef struct ccsr_ddr { u32 cs0_bnds; /* Chip Select 0 Memory Bounds */ u8 res1[4]; @@ -739,7 +739,7 @@ typedef struct immap { u8 dll_ddr[0x100]; u8 dll_lbc[0x100]; u8 res1[0xE00]; -#if defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3) ccsr_ddr_t ddr; /* DDR Memory Controller Memory */ #else ddr83xx_t ddr; /* DDR Memory Controller Memory */ @@ -1029,7 +1029,7 @@ typedef struct immap { #endif #define CONFIG_SYS_MPC8xxx_DDR_OFFSET (0x2000) -#define CONFIG_SYS_MPC8xxx_DDR_ADDR \ +#define CONFIG_SYS_FSL_DDR_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET) #define CONFIG_SYS_MPC83xx_DMA_OFFSET (0x8000) #define CONFIG_SYS_MPC83xx_DMA_ADDR \ diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index 631261857e..d479216850 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -3048,11 +3048,11 @@ struct ccsr_pman { (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_RCPM_OFFSET) #define CONFIG_SYS_MPC85xx_ECM_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ECM_OFFSET) -#define CONFIG_SYS_MPC8xxx_DDR_ADDR \ +#define CONFIG_SYS_FSL_DDR_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET) -#define CONFIG_SYS_MPC8xxx_DDR2_ADDR \ +#define CONFIG_SYS_FSL_DDR2_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR2_OFFSET) -#define CONFIG_SYS_MPC8xxx_DDR3_ADDR \ +#define CONFIG_SYS_FSL_DDR3_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR3_OFFSET) #define CONFIG_SYS_LBC_ADDR \ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET) diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h index 2a704fe6b7..046a434719 100644 --- a/arch/powerpc/include/asm/immap_86xx.h +++ b/arch/powerpc/include/asm/immap_86xx.h @@ -1253,9 +1253,9 @@ typedef struct immap { extern immap_t *immr; #define CONFIG_SYS_MPC8xxx_DDR_OFFSET 0x2000 -#define CONFIG_SYS_MPC8xxx_DDR_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET) +#define CONFIG_SYS_FSL_DDR_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET) #define CONFIG_SYS_MPC8xxx_DDR2_OFFSET 0x6000 -#define CONFIG_SYS_MPC8xxx_DDR2_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR2_OFFSET) +#define CONFIG_SYS_FSL_DDR2_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR2_OFFSET) #define CONFIG_SYS_MPC86xx_DMA_OFFSET 0x21000 #define CONFIG_SYS_MPC86xx_DMA_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DMA_OFFSET) #define CONFIG_SYS_MPC86xx_PIC_OFFSET 0x40000 diff --git a/board/exmeritus/hww1u1a/ddr.c b/board/exmeritus/hww1u1a/ddr.c index 23a71d5af5..e1f6865f42 100644 --- a/board/exmeritus/hww1u1a/ddr.c +++ b/board/exmeritus/hww1u1a/ddr.c @@ -9,8 +9,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/exmeritus/hww1u1a/hww1u1a.c b/board/exmeritus/hww1u1a/hww1u1a.c index 7c11e38d1c..104987a9b6 100644 --- a/board/exmeritus/hww1u1a/hww1u1a.c +++ b/board/exmeritus/hww1u1a/hww1u1a.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ int checkboard(void) * and delay a while before we continue. */ if (mpc85xx_gpio_get(GPIO_RESETS)) { - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; puts("Debugger detected... extra device reset enabled!\n"); diff --git a/board/freescale/b4860qds/ddr.c b/board/freescale/b4860qds/ddr.c index 2d14923139..187c3b3ebc 100644 --- a/board/freescale/b4860qds/ddr.c +++ b/board/freescale/b4860qds/ddr.c @@ -9,11 +9,11 @@ #include #include #include +#include #include -#include -#include +#include +#include #include -#include <../arch/powerpc/cpu/mpc8xxx/ddr/ddr.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/board/freescale/bsc9131rdb/ddr.c b/board/freescale/bsc9131rdb/ddr.c index a9e92f2ae0..339c576256 100644 --- a/board/freescale/bsc9131rdb/ddr.c +++ b/board/freescale/bsc9131rdb/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/bsc9131rdb/spl_minimal.c b/board/freescale/bsc9131rdb/spl_minimal.c index dd5ea95e33..974627163a 100644 --- a/board/freescale/bsc9131rdb/spl_minimal.c +++ b/board/freescale/bsc9131rdb/spl_minimal.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -20,7 +20,7 @@ DECLARE_GLOBAL_DATA_PTR; */ static void sdram_init(void) { - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; __raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds); __raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config); diff --git a/board/freescale/bsc9132qds/bsc9132qds.c b/board/freescale/bsc9132qds/bsc9132qds.c index a895e4e297..31bbf62ee5 100644 --- a/board/freescale/bsc9132qds/bsc9132qds.c +++ b/board/freescale/bsc9132qds/bsc9132qds.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #ifdef CONFIG_PCI #include @@ -134,7 +134,7 @@ void dsp_ddr_configure(void) *to the DSP DDR controller as connected DDR memories are similar. */ ccsr_ddr_t __iomem *pa_ddr = - (ccsr_ddr_t __iomem *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + (ccsr_ddr_t __iomem *)CONFIG_SYS_FSL_DDR_ADDR; ccsr_ddr_t temp_ddr; ccsr_ddr_t __iomem *dsp_ddr = (ccsr_ddr_t __iomem *)CONFIG_SYS_FSL_DSP_CCSR_DDR_ADDR; diff --git a/board/freescale/bsc9132qds/ddr.c b/board/freescale/bsc9132qds/ddr.c index b3130be86d..43f163a2c6 100644 --- a/board/freescale/bsc9132qds/ddr.c +++ b/board/freescale/bsc9132qds/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/bsc9132qds/spl_minimal.c b/board/freescale/bsc9132qds/spl_minimal.c index 2bf0a0cfa8..0249dc587f 100644 --- a/board/freescale/bsc9132qds/spl_minimal.c +++ b/board/freescale/bsc9132qds/spl_minimal.c @@ -10,14 +10,14 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; static void sdram_init(void) { - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; #if CONFIG_DDR_CLK_FREQ == 100000000 __raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds); __raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config); diff --git a/board/freescale/c29xpcie/ddr.c b/board/freescale/c29xpcie/ddr.c index 57a9b610ea..968655c1b3 100644 --- a/board/freescale/c29xpcie/ddr.c +++ b/board/freescale/c29xpcie/ddr.c @@ -6,8 +6,8 @@ #include #include -#include -#include +#include +#include #include "cpld.h" diff --git a/board/freescale/corenet_ds/ddr.c b/board/freescale/corenet_ds/ddr.c index 18e2ff617b..e7e893a1ae 100644 --- a/board/freescale/corenet_ds/ddr.c +++ b/board/freescale/corenet_ds/ddr.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/board/freescale/corenet_ds/eth_p4080.c b/board/freescale/corenet_ds/eth_p4080.c index e5beb55177..5cbec7f5f2 100644 --- a/board/freescale/corenet_ds/eth_p4080.c +++ b/board/freescale/corenet_ds/eth_p4080.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/corenet_ds/p3041ds_ddr.c b/board/freescale/corenet_ds/p3041ds_ddr.c index 5a8ed94b04..4dead9c045 100644 --- a/board/freescale/corenet_ds/p3041ds_ddr.c +++ b/board/freescale/corenet_ds/p3041ds_ddr.c @@ -7,7 +7,7 @@ */ #include -#include +#include fixed_ddr_parm_t fixed_ddr_parm_0[] = { {0, 0, NULL} diff --git a/board/freescale/corenet_ds/p4080ds_ddr.c b/board/freescale/corenet_ds/p4080ds_ddr.c index 844e1d736a..d572a5fbed 100644 --- a/board/freescale/corenet_ds/p4080ds_ddr.c +++ b/board/freescale/corenet_ds/p4080ds_ddr.c @@ -7,7 +7,7 @@ */ #include -#include +#include #define CONFIG_SYS_DDR_TIMING_3_1200 0x01030000 #define CONFIG_SYS_DDR_TIMING_0_1200 0xCC550104 diff --git a/board/freescale/corenet_ds/p5020ds_ddr.c b/board/freescale/corenet_ds/p5020ds_ddr.c index e65de364d7..9aaf6db997 100644 --- a/board/freescale/corenet_ds/p5020ds_ddr.c +++ b/board/freescale/corenet_ds/p5020ds_ddr.c @@ -7,7 +7,7 @@ */ #include -#include +#include fixed_ddr_parm_t fixed_ddr_parm_0[] = { {0, 0, NULL} diff --git a/board/freescale/corenet_ds/p5040ds_ddr.c b/board/freescale/corenet_ds/p5040ds_ddr.c index e65de364d7..9aaf6db997 100644 --- a/board/freescale/corenet_ds/p5040ds_ddr.c +++ b/board/freescale/corenet_ds/p5040ds_ddr.c @@ -7,7 +7,7 @@ */ #include -#include +#include fixed_ddr_parm_t fixed_ddr_parm_0[] = { {0, 0, NULL} diff --git a/board/freescale/mpc8349emds/Makefile b/board/freescale/mpc8349emds/Makefile index 23880f52f5..5c315f9f68 100644 --- a/board/freescale/mpc8349emds/Makefile +++ b/board/freescale/mpc8349emds/Makefile @@ -7,4 +7,4 @@ obj-y += mpc8349emds.o obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o diff --git a/board/freescale/mpc8349emds/ddr.c b/board/freescale/mpc8349emds/ddr.c index 3d257d0fbf..aae003d121 100644 --- a/board/freescale/mpc8349emds/ddr.c +++ b/board/freescale/mpc8349emds/ddr.c @@ -6,8 +6,8 @@ #include -#include -#include +#include +#include struct board_specific_parameters { u32 n_ranks; diff --git a/board/freescale/mpc8349emds/mpc8349emds.c b/board/freescale/mpc8349emds/mpc8349emds.c index ec48487294..d9092201aa 100644 --- a/board/freescale/mpc8349emds/mpc8349emds.c +++ b/board/freescale/mpc8349emds/mpc8349emds.c @@ -12,8 +12,8 @@ #include #include #include -#ifdef CONFIG_FSL_DDR2 -#include +#ifdef CONFIG_SYS_FSL_DDR2 +#include #else #include #endif @@ -57,7 +57,7 @@ phys_size_t initdram (int board_type) /* DDR SDRAM - Main SODIMM */ im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_BASE & LAWBAR_BAR; #if defined(CONFIG_SPD_EEPROM) -#ifndef CONFIG_FSL_DDR2 +#ifndef CONFIG_SYS_FSL_DDR2 msize = spd_sdram() * 1024 * 1024; #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) ddr_enable_ecc(msize); diff --git a/board/freescale/mpc8536ds/ddr.c b/board/freescale/mpc8536ds/ddr.c index d10370c9f2..ebe3ba460c 100644 --- a/board/freescale/mpc8536ds/ddr.c +++ b/board/freescale/mpc8536ds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8536ds/mpc8536ds.c b/board/freescale/mpc8536ds/mpc8536ds.c index 5daab692c6..59e9a35089 100644 --- a/board/freescale/mpc8536ds/mpc8536ds.c +++ b/board/freescale/mpc8536ds/mpc8536ds.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8540ads/ddr.c b/board/freescale/mpc8540ads/ddr.c index 9e79815278..41d4cfe738 100644 --- a/board/freescale/mpc8540ads/ddr.c +++ b/board/freescale/mpc8540ads/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8540ads/mpc8540ads.c b/board/freescale/mpc8540ads/mpc8540ads.c index 175eefcc6b..97a5d19b5e 100644 --- a/board/freescale/mpc8540ads/mpc8540ads.c +++ b/board/freescale/mpc8540ads/mpc8540ads.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -168,7 +168,7 @@ void lbc_sdram_init(void) phys_size_t fixed_sdram(void) { #ifndef CONFIG_SYS_RAMBOOT - volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); + volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); ddr->cs0_bnds = CONFIG_SYS_DDR_CS0_BNDS; ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG; diff --git a/board/freescale/mpc8541cds/ddr.c b/board/freescale/mpc8541cds/ddr.c index 78d73b0ea8..d2ac6c4ad4 100644 --- a/board/freescale/mpc8541cds/ddr.c +++ b/board/freescale/mpc8541cds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8541cds/mpc8541cds.c b/board/freescale/mpc8541cds/mpc8541cds.c index 8115e5c69b..7b264dddd1 100644 --- a/board/freescale/mpc8541cds/mpc8541cds.c +++ b/board/freescale/mpc8541cds/mpc8541cds.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8544ds/ddr.c b/board/freescale/mpc8544ds/ddr.c index 6cf9bc1d75..aa30cabb03 100644 --- a/board/freescale/mpc8544ds/ddr.c +++ b/board/freescale/mpc8544ds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8544ds/mpc8544ds.c b/board/freescale/mpc8544ds/mpc8544ds.c index dfd8fa6522..1b33db6f31 100644 --- a/board/freescale/mpc8544ds/mpc8544ds.c +++ b/board/freescale/mpc8544ds/mpc8544ds.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8548cds/ddr.c b/board/freescale/mpc8548cds/ddr.c index 996ffe206d..b31ea3432e 100644 --- a/board/freescale/mpc8548cds/ddr.c +++ b/board/freescale/mpc8548cds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8548cds/mpc8548cds.c b/board/freescale/mpc8548cds/mpc8548cds.c index 51e4bb5dcb..ca9b43c6b6 100644 --- a/board/freescale/mpc8548cds/mpc8548cds.c +++ b/board/freescale/mpc8548cds/mpc8548cds.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8555cds/ddr.c b/board/freescale/mpc8555cds/ddr.c index 78d73b0ea8..d2ac6c4ad4 100644 --- a/board/freescale/mpc8555cds/ddr.c +++ b/board/freescale/mpc8555cds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8555cds/mpc8555cds.c b/board/freescale/mpc8555cds/mpc8555cds.c index e2093d1bbc..de5f5669e6 100644 --- a/board/freescale/mpc8555cds/mpc8555cds.c +++ b/board/freescale/mpc8555cds/mpc8555cds.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8560ads/ddr.c b/board/freescale/mpc8560ads/ddr.c index 9e79815278..41d4cfe738 100644 --- a/board/freescale/mpc8560ads/ddr.c +++ b/board/freescale/mpc8560ads/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8560ads/mpc8560ads.c b/board/freescale/mpc8560ads/mpc8560ads.c index 90a2522cb9..7104e33156 100644 --- a/board/freescale/mpc8560ads/mpc8560ads.c +++ b/board/freescale/mpc8560ads/mpc8560ads.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -373,7 +373,7 @@ void lbc_sdram_init(void) phys_size_t fixed_sdram(void) { #ifndef CONFIG_SYS_RAMBOOT - volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); + volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); ddr->cs0_bnds = CONFIG_SYS_DDR_CS0_BNDS; ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG; diff --git a/board/freescale/mpc8568mds/ddr.c b/board/freescale/mpc8568mds/ddr.c index b1f4f1f848..6db92ef2da 100644 --- a/board/freescale/mpc8568mds/ddr.c +++ b/board/freescale/mpc8568mds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8568mds/mpc8568mds.c b/board/freescale/mpc8568mds/mpc8568mds.c index ae80697b38..a8fdcb5f91 100644 --- a/board/freescale/mpc8568mds/mpc8568mds.c +++ b/board/freescale/mpc8568mds/mpc8568mds.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8569mds/ddr.c b/board/freescale/mpc8569mds/ddr.c index 68f686b7e6..ef404b1d6f 100644 --- a/board/freescale/mpc8569mds/ddr.c +++ b/board/freescale/mpc8569mds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8569mds/mpc8569mds.c b/board/freescale/mpc8569mds/mpc8569mds.c index c928a964f9..60f55773da 100644 --- a/board/freescale/mpc8569mds/mpc8569mds.c +++ b/board/freescale/mpc8569mds/mpc8569mds.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -231,7 +231,7 @@ int checkboard (void) #if !defined(CONFIG_SPD_EEPROM) phys_size_t fixed_sdram(void) { - volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; uint d_init; out_be32(&ddr->cs0_bnds, CONFIG_SYS_DDR_CS0_BNDS); diff --git a/board/freescale/mpc8572ds/ddr.c b/board/freescale/mpc8572ds/ddr.c index 52e4f4224c..2bfc1a170c 100644 --- a/board/freescale/mpc8572ds/ddr.c +++ b/board/freescale/mpc8572ds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include struct board_specific_parameters { u32 n_ranks; diff --git a/board/freescale/mpc8572ds/mpc8572ds.c b/board/freescale/mpc8572ds/mpc8572ds.c index 657df6a718..2fb4257132 100644 --- a/board/freescale/mpc8572ds/mpc8572ds.c +++ b/board/freescale/mpc8572ds/mpc8572ds.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8610hpcd/Makefile b/board/freescale/mpc8610hpcd/Makefile index 933ea179ba..2613004f89 100644 --- a/board/freescale/mpc8610hpcd/Makefile +++ b/board/freescale/mpc8610hpcd/Makefile @@ -4,6 +4,6 @@ # obj-y += mpc8610hpcd.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o obj-y += law.o obj-$(CONFIG_FSL_DIU_FB) += mpc8610hpcd_diu.o diff --git a/board/freescale/mpc8610hpcd/ddr.c b/board/freescale/mpc8610hpcd/ddr.c index 6cf9bc1d75..aa30cabb03 100644 --- a/board/freescale/mpc8610hpcd/ddr.c +++ b/board/freescale/mpc8610hpcd/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd.c b/board/freescale/mpc8610hpcd/mpc8610hpcd.c index ffdcf2444c..aa99623a43 100644 --- a/board/freescale/mpc8610hpcd/mpc8610hpcd.c +++ b/board/freescale/mpc8610hpcd/mpc8610hpcd.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/mpc8641hpcn/Makefile b/board/freescale/mpc8641hpcn/Makefile index 8d53af8227..86c70bcb9d 100644 --- a/board/freescale/mpc8641hpcn/Makefile +++ b/board/freescale/mpc8641hpcn/Makefile @@ -7,4 +7,4 @@ obj-y += mpc8641hpcn.o obj-y += law.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o diff --git a/board/freescale/mpc8641hpcn/ddr.c b/board/freescale/mpc8641hpcn/ddr.c index 651652a77d..7cd0395651 100644 --- a/board/freescale/mpc8641hpcn/ddr.c +++ b/board/freescale/mpc8641hpcn/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include struct board_specific_parameters { u32 n_ranks; diff --git a/board/freescale/mpc8641hpcn/mpc8641hpcn.c b/board/freescale/mpc8641hpcn/mpc8641hpcn.c index 46a543ebcc..0cd9df1cc9 100644 --- a/board/freescale/mpc8641hpcn/mpc8641hpcn.c +++ b/board/freescale/mpc8641hpcn/mpc8641hpcn.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/p1010rdb/ddr.c b/board/freescale/p1010rdb/ddr.c index ab1b41d832..b0d95ea006 100644 --- a/board/freescale/p1010rdb/ddr.c +++ b/board/freescale/p1010rdb/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/p1010rdb/spl_minimal.c b/board/freescale/p1010rdb/spl_minimal.c index d0e712eb30..aa2a3448c5 100644 --- a/board/freescale/p1010rdb/spl_minimal.c +++ b/board/freescale/p1010rdb/spl_minimal.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -19,7 +19,7 @@ DECLARE_GLOBAL_DATA_PTR; void sdram_init(void) { - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; u32 ddr_ratio; unsigned long ddr_freq_mhz; diff --git a/board/freescale/p1022ds/ddr.c b/board/freescale/p1022ds/ddr.c index 94d2c2b0db..09212bcee8 100644 --- a/board/freescale/p1022ds/ddr.c +++ b/board/freescale/p1022ds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include struct board_specific_parameters { u32 n_ranks; diff --git a/board/freescale/p1022ds/p1022ds.c b/board/freescale/p1022ds/p1022ds.c index 3d1951cdba..ba789a4daf 100644 --- a/board/freescale/p1022ds/p1022ds.c +++ b/board/freescale/p1022ds/p1022ds.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/p1022ds/spl_minimal.c b/board/freescale/p1022ds/spl_minimal.c index 8b34396843..6c7e1ac3cb 100644 --- a/board/freescale/p1022ds/spl_minimal.c +++ b/board/freescale/p1022ds/spl_minimal.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include const static u32 sysclk_tbl[] = { diff --git a/board/freescale/p1023rdb/ddr.c b/board/freescale/p1023rdb/ddr.c index 9fb61fdab3..d587df527a 100644 --- a/board/freescale/p1023rdb/ddr.c +++ b/board/freescale/p1023rdb/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/p1023rdb/p1023rdb.c b/board/freescale/p1023rdb/p1023rdb.c index b52b092069..d2d4f8390a 100644 --- a/board/freescale/p1023rdb/p1023rdb.c +++ b/board/freescale/p1023rdb/p1023rdb.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/p1023rds/p1023rds.c b/board/freescale/p1023rds/p1023rds.c index 7c54b65c1d..2cfcdc41f3 100644 --- a/board/freescale/p1023rds/p1023rds.c +++ b/board/freescale/p1023rds/p1023rds.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -58,7 +58,7 @@ int checkboard(void) phys_size_t fixed_sdram(void) { #ifndef CONFIG_SYS_RAMBOOT - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; set_next_law(0, LAW_SIZE_2G, LAW_TRGT_IF_DDR_1); diff --git a/board/freescale/p1_p2_rdb/ddr.c b/board/freescale/p1_p2_rdb/ddr.c index 5bee22e638..17d3beac39 100644 --- a/board/freescale/p1_p2_rdb/ddr.c +++ b/board/freescale/p1_p2_rdb/ddr.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/board/freescale/p1_p2_rdb_pc/ddr.c b/board/freescale/p1_p2_rdb_pc/ddr.c index 81cc0930bc..946d5032e7 100644 --- a/board/freescale/p1_p2_rdb_pc/ddr.c +++ b/board/freescale/p1_p2_rdb_pc/ddr.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c index 50553dacd9..966abb24a6 100644 --- a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c +++ b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/p1_p2_rdb_pc/spl_minimal.c b/board/freescale/p1_p2_rdb_pc/spl_minimal.c index adfa7b1e0f..92437bc787 100644 --- a/board/freescale/p1_p2_rdb_pc/spl_minimal.c +++ b/board/freescale/p1_p2_rdb_pc/spl_minimal.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/board/freescale/p1_twr/ddr.c b/board/freescale/p1_twr/ddr.c index 67f69d79bd..a2ce75a40d 100644 --- a/board/freescale/p1_twr/ddr.c +++ b/board/freescale/p1_twr/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/board/freescale/p1_twr/p1_twr.c b/board/freescale/p1_twr/p1_twr.c index ea8db6fc07..0e0d0587d7 100644 --- a/board/freescale/p1_twr/p1_twr.c +++ b/board/freescale/p1_twr/p1_twr.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/freescale/p2020come/ddr.c b/board/freescale/p2020come/ddr.c index da804771fb..b642e1255c 100644 --- a/board/freescale/p2020come/ddr.c +++ b/board/freescale/p2020come/ddr.c @@ -5,8 +5,8 @@ */ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/freescale/p2020ds/ddr.c b/board/freescale/p2020ds/ddr.c index b12141f296..debe70b18b 100644 --- a/board/freescale/p2020ds/ddr.c +++ b/board/freescale/p2020ds/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include struct board_specific_parameters { u32 n_ranks; @@ -37,7 +37,7 @@ static const struct board_specific_parameters dimm0[] = { * num| hi| clk| cpo|wrdata|2T * ranks| mhz|adjst| | delay| */ -#ifdef CONFIG_FSL_DDR2 +#ifdef CONFIG_SYS_FSL_DDR2 {2, 549, 4, 0x1f, 2, 0}, {2, 680, 4, 0x1f, 3, 0}, {2, 850, 4, 0x1f, 4, 0}, diff --git a/board/freescale/p2020ds/p2020ds.c b/board/freescale/p2020ds/p2020ds.c index 58a42231a9..dd8c6b10fb 100644 --- a/board/freescale/p2020ds/p2020ds.c +++ b/board/freescale/p2020ds/p2020ds.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -68,7 +68,7 @@ int checkboard(void) phys_size_t fixed_sdram(void) { - volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; uint d_init; ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG; diff --git a/board/freescale/p2041rdb/ddr.c b/board/freescale/p2041rdb/ddr.c index cc1bfae394..b8bbcdf2a8 100644 --- a/board/freescale/p2041rdb/ddr.c +++ b/board/freescale/p2041rdb/ddr.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include struct board_specific_parameters { diff --git a/board/freescale/t1040qds/ddr.c b/board/freescale/t1040qds/ddr.c index 4fd17da160..da89a36b96 100644 --- a/board/freescale/t1040qds/ddr.c +++ b/board/freescale/t1040qds/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include "ddr.h" diff --git a/board/freescale/t104xrdb/ddr.c b/board/freescale/t104xrdb/ddr.c index 8f58dd6832..9009afa3ad 100644 --- a/board/freescale/t104xrdb/ddr.c +++ b/board/freescale/t104xrdb/ddr.c @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include "ddr.h" diff --git a/board/freescale/t4qds/ddr.c b/board/freescale/t4qds/ddr.c index d70c31051d..7586cc3c4b 100644 --- a/board/freescale/t4qds/ddr.c +++ b/board/freescale/t4qds/ddr.c @@ -10,8 +10,8 @@ #include #include #include -#include -#include +#include +#include #include #include "ddr.h" diff --git a/board/freescale/t4qds/eth.c b/board/freescale/t4qds/eth.c index b5f488bcba..24cf907430 100644 --- a/board/freescale/t4qds/eth.c +++ b/board/freescale/t4qds/eth.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/gdsys/p1022/controlcenterd.c b/board/gdsys/p1022/controlcenterd.c index 81c22bc94c..8ccd9ce6ba 100644 --- a/board/gdsys/p1022/controlcenterd.c +++ b/board/gdsys/p1022/controlcenterd.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/gdsys/p1022/ddr.c b/board/gdsys/p1022/ddr.c index 4a652de430..7596736bfd 100644 --- a/board/gdsys/p1022/ddr.c +++ b/board/gdsys/p1022/ddr.c @@ -12,8 +12,8 @@ #include #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, unsigned int ctrl_num) diff --git a/board/keymile/kmp204x/ddr.c b/board/keymile/kmp204x/ddr.c index bd425aab1a..34ac6979bd 100644 --- a/board/keymile/kmp204x/ddr.c +++ b/board/keymile/kmp204x/ddr.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/sbc8548/Makefile b/board/sbc8548/Makefile index b1e32a668b..4c9b6cd60c 100644 --- a/board/sbc8548/Makefile +++ b/board/sbc8548/Makefile @@ -11,4 +11,4 @@ obj-y += sbc8548.o obj-y += law.o obj-y += tlb.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o diff --git a/board/sbc8548/ddr.c b/board/sbc8548/ddr.c index 9508561133..8817103ba7 100644 --- a/board/sbc8548/ddr.c +++ b/board/sbc8548/ddr.c @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, @@ -91,7 +91,7 @@ void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) */ phys_size_t fixed_sdram(void) { - volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); + volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); out_be32(&ddr->cs0_bnds, 0x0000007f); out_be32(&ddr->cs1_bnds, 0x008000ff); diff --git a/board/sbc8548/sbc8548.c b/board/sbc8548/sbc8548.c index 3cd945f2c2..d584276253 100644 --- a/board/sbc8548/sbc8548.c +++ b/board/sbc8548/sbc8548.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/sbc8641d/Makefile b/board/sbc8641d/Makefile index 9626b06a5a..a9b20266bc 100644 --- a/board/sbc8641d/Makefile +++ b/board/sbc8641d/Makefile @@ -7,4 +7,4 @@ obj-y += sbc8641d.o obj-y += law.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o diff --git a/board/sbc8641d/ddr.c b/board/sbc8641d/ddr.c index 996ffe206d..b31ea3432e 100644 --- a/board/sbc8641d/ddr.c +++ b/board/sbc8641d/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/sbc8641d/sbc8641d.c b/board/sbc8641d/sbc8641d.c index 0b5e8dc17e..8160c7b580 100644 --- a/board/sbc8641d/sbc8641d.c +++ b/board/sbc8641d/sbc8641d.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/socrates/Makefile b/board/socrates/Makefile index 0a088100e8..79bda718d5 100644 --- a/board/socrates/Makefile +++ b/board/socrates/Makefile @@ -12,4 +12,4 @@ obj-y += law.o obj-y += tlb.o obj-y += nand.o obj-y += sdram.o -obj-$(CONFIG_FSL_DDR2) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr.o diff --git a/board/socrates/ddr.c b/board/socrates/ddr.c index e9db476f48..6bad4da394 100644 --- a/board/socrates/ddr.c +++ b/board/socrates/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/socrates/sdram.c b/board/socrates/sdram.c index 313efae90f..356e8e82e7 100644 --- a/board/socrates/sdram.c +++ b/board/socrates/sdram.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,7 +24,7 @@ */ phys_size_t fixed_sdram(void) { - volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR); + volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); /* * Disable memory controller. diff --git a/board/stx/stxgp3/Makefile b/board/stx/stxgp3/Makefile index 9b724347de..78e2d6c96f 100644 --- a/board/stx/stxgp3/Makefile +++ b/board/stx/stxgp3/Makefile @@ -9,4 +9,4 @@ obj-y += stxgp3.o obj-y += law.o obj-y += tlb.o obj-y += flash.o -obj-$(CONFIG_FSL_DDR1) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR1) += ddr.o diff --git a/board/stx/stxgp3/ddr.c b/board/stx/stxgp3/ddr.c index 9e79815278..41d4cfe738 100644 --- a/board/stx/stxgp3/ddr.c +++ b/board/stx/stxgp3/ddr.c @@ -8,8 +8,8 @@ #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/stx/stxgp3/stxgp3.c b/board/stx/stxgp3/stxgp3.c index bd683f6af8..c80d5259ce 100644 --- a/board/stx/stxgp3/stxgp3.c +++ b/board/stx/stxgp3/stxgp3.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/stx/stxssa/Makefile b/board/stx/stxssa/Makefile index 17e0aaea7e..b1d4b0a270 100644 --- a/board/stx/stxssa/Makefile +++ b/board/stx/stxssa/Makefile @@ -8,4 +8,4 @@ obj-y += stxssa.o obj-y += law.o obj-y += tlb.o -obj-$(CONFIG_FSL_DDR1) += ddr.o +obj-$(CONFIG_SYS_FSL_DDR1) += ddr.o diff --git a/board/stx/stxssa/ddr.c b/board/stx/stxssa/ddr.c index 71be3bf636..1ccd4c5183 100644 --- a/board/stx/stxssa/ddr.c +++ b/board/stx/stxssa/ddr.c @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include void fsl_ddr_board_options(memctl_options_t *popts, dimm_params_t *pdimm, diff --git a/board/stx/stxssa/stxssa.c b/board/stx/stxssa/stxssa.c index c08a18bffe..f5c3d750ce 100644 --- a/board/stx/stxssa/stxssa.c +++ b/board/stx/stxssa/stxssa.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/board/xes/xpedite517x/ddr.c b/board/xes/xpedite517x/ddr.c index f48c02fdae..fd602ea7e0 100644 --- a/board/xes/xpedite517x/ddr.c +++ b/board/xes/xpedite517x/ddr.c @@ -7,8 +7,8 @@ #include #include -#include -#include +#include +#include void get_spd(ddr2_spd_eeprom_t *spd, u8 i2c_address) { diff --git a/board/xes/xpedite517x/xpedite517x.c b/board/xes/xpedite517x/xpedite517x.c index 1782042510..b7ad349502 100644 --- a/board/xes/xpedite517x/xpedite517x.c +++ b/board/xes/xpedite517x/xpedite517x.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include diff --git a/board/xes/xpedite520x/ddr.c b/board/xes/xpedite520x/ddr.c index 3671cb8af9..5c5eadc93f 100644 --- a/board/xes/xpedite520x/ddr.c +++ b/board/xes/xpedite520x/ddr.c @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include void get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address) { diff --git a/board/xes/xpedite537x/ddr.c b/board/xes/xpedite537x/ddr.c index f41ae73755..56b5a187d8 100644 --- a/board/xes/xpedite537x/ddr.c +++ b/board/xes/xpedite537x/ddr.c @@ -8,8 +8,8 @@ #include #include -#include -#include +#include +#include void get_spd(ddr2_spd_eeprom_t *spd, u8 i2c_address) { diff --git a/board/xes/xpedite550x/ddr.c b/board/xes/xpedite550x/ddr.c index 9fc6f048c4..0c0605e3a9 100644 --- a/board/xes/xpedite550x/ddr.c +++ b/board/xes/xpedite550x/ddr.c @@ -8,8 +8,8 @@ #include #include -#include -#include +#include +#include void get_spd(ddr3_spd_eeprom_t *spd, u8 i2c_address) { diff --git a/drivers/ddr/fsl/Makefile b/drivers/ddr/fsl/Makefile new file mode 100644 index 0000000000..a328b43209 --- /dev/null +++ b/drivers/ddr/fsl/Makefile @@ -0,0 +1,34 @@ +# +# Copyright 2008-2011 Freescale Semiconductor, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# Version 2 as published by the Free Software Foundation. +# + +obj-$(CONFIG_SYS_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \ + lc_common_dimm_params.o + +obj-$(CONFIG_SYS_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \ + lc_common_dimm_params.o + +obj-$(CONFIG_SYS_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \ + lc_common_dimm_params.o +ifdef CONFIG_DDR_SPD +SPD := y +endif +ifdef CONFIG_SPD_EEPROM +SPD := y +endif +ifdef SPD +obj-$(CONFIG_SYS_FSL_DDR1) += ddr1_dimm_params.o +obj-$(CONFIG_SYS_FSL_DDR2) += ddr2_dimm_params.o +obj-$(CONFIG_SYS_FSL_DDR3) += ddr3_dimm_params.o +endif + +obj-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o +obj-$(CONFIG_SYS_FSL_DDRC_GEN1) += mpc85xx_ddr_gen1.o +obj-$(CONFIG_SYS_FSL_DDRC_GEN2) += mpc85xx_ddr_gen2.o +obj-$(CONFIG_SYS_FSL_DDRC_GEN3) += mpc85xx_ddr_gen3.o +obj-$(CONFIG_SYS_FSL_DDR_86XX) += mpc86xx_ddr.o +obj-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c new file mode 100644 index 0000000000..aed4569cb4 --- /dev/null +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -0,0 +1,1657 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. + * Based on code from spd_sdram.c + * Author: James Yang [at freescale.com] + */ + +#include +#include + +#include +#include + +#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR + +static u32 fsl_ddr_get_version(void) +{ + ccsr_ddr_t *ddr; + u32 ver_major_minor_errata; + + ddr = (void *)_DDR_ADDR; + ver_major_minor_errata = (in_be32(&ddr->ip_rev1) & 0xFFFF) << 8; + ver_major_minor_errata |= (in_be32(&ddr->ip_rev2) & 0xFF00) >> 8; + + return ver_major_minor_errata; +} + +unsigned int picos_to_mclk(unsigned int picos); + +/* + * Determine Rtt value. + * + * This should likely be either board or controller specific. + * + * Rtt(nominal) - DDR2: + * 0 = Rtt disabled + * 1 = 75 ohm + * 2 = 150 ohm + * 3 = 50 ohm + * Rtt(nominal) - DDR3: + * 0 = Rtt disabled + * 1 = 60 ohm + * 2 = 120 ohm + * 3 = 40 ohm + * 4 = 20 ohm + * 5 = 30 ohm + * + * FIXME: Apparently 8641 needs a value of 2 + * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572 + * + * FIXME: There was some effort down this line earlier: + * + * unsigned int i; + * for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) { + * if (popts->dimmslot[i].num_valid_cs + * && (popts->cs_local_opts[2*i].odt_rd_cfg + * || popts->cs_local_opts[2*i].odt_wr_cfg)) { + * rtt = 2; + * break; + * } + * } + */ +static inline int fsl_ddr_get_rtt(void) +{ + int rtt; + +#if defined(CONFIG_SYS_FSL_DDR1) + rtt = 0; +#elif defined(CONFIG_SYS_FSL_DDR2) + rtt = 3; +#else + rtt = 0; +#endif + + return rtt; +} + +/* + * compute the CAS write latency according to DDR3 spec + * CWL = 5 if tCK >= 2.5ns + * 6 if 2.5ns > tCK >= 1.875ns + * 7 if 1.875ns > tCK >= 1.5ns + * 8 if 1.5ns > tCK >= 1.25ns + * 9 if 1.25ns > tCK >= 1.07ns + * 10 if 1.07ns > tCK >= 0.935ns + * 11 if 0.935ns > tCK >= 0.833ns + * 12 if 0.833ns > tCK >= 0.75ns + */ +static inline unsigned int compute_cas_write_latency(void) +{ + unsigned int cwl; + const unsigned int mclk_ps = get_memory_clk_period_ps(); + + if (mclk_ps >= 2500) + cwl = 5; + else if (mclk_ps >= 1875) + cwl = 6; + else if (mclk_ps >= 1500) + cwl = 7; + else if (mclk_ps >= 1250) + cwl = 8; + else if (mclk_ps >= 1070) + cwl = 9; + else if (mclk_ps >= 935) + cwl = 10; + else if (mclk_ps >= 833) + cwl = 11; + else if (mclk_ps >= 750) + cwl = 12; + else { + cwl = 12; + printf("Warning: CWL is out of range\n"); + } + return cwl; +} + +/* Chip Select Configuration (CSn_CONFIG) */ +static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const dimm_params_t *dimm_params) +{ + unsigned int cs_n_en = 0; /* Chip Select enable */ + unsigned int intlv_en = 0; /* Memory controller interleave enable */ + unsigned int intlv_ctl = 0; /* Interleaving control */ + unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */ + unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */ + unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */ + unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */ + unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */ + unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */ + int go_config = 0; + + /* Compute CS_CONFIG only for existing ranks of each DIMM. */ + switch (i) { + case 0: + if (dimm_params[dimm_number].n_ranks > 0) { + go_config = 1; + /* These fields only available in CS0_CONFIG */ + if (!popts->memctl_interleaving) + break; + switch (popts->memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + intlv_en = popts->memctl_interleaving; + intlv_ctl = popts->memctl_interleaving_mode; + break; + default: + break; + } + } + break; + case 1: + if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \ + (dimm_number == 1 && dimm_params[1].n_ranks > 0)) + go_config = 1; + break; + case 2: + if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \ + (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0)) + go_config = 1; + break; + case 3: + if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \ + (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \ + (dimm_number == 3 && dimm_params[3].n_ranks > 0)) + go_config = 1; + break; + default: + break; + } + if (go_config) { + unsigned int n_banks_per_sdram_device; + cs_n_en = 1; + ap_n_en = popts->cs_local_opts[i].auto_precharge; + odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg; + odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg; + n_banks_per_sdram_device + = dimm_params[dimm_number].n_banks_per_sdram_device; + ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2; + row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12; + col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8; + } + ddr->cs[i].config = (0 + | ((cs_n_en & 0x1) << 31) + | ((intlv_en & 0x3) << 29) + | ((intlv_ctl & 0xf) << 24) + | ((ap_n_en & 0x1) << 23) + + /* XXX: some implementation only have 1 bit starting at left */ + | ((odt_rd_cfg & 0x7) << 20) + + /* XXX: Some implementation only have 1 bit starting at left */ + | ((odt_wr_cfg & 0x7) << 16) + + | ((ba_bits_cs_n & 0x3) << 14) + | ((row_bits_cs_n & 0x7) << 8) + | ((col_bits_cs_n & 0x7) << 0) + ); + debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config); +} + +/* Chip Select Configuration 2 (CSn_CONFIG_2) */ +/* FIXME: 8572 */ +static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int pasr_cfg = 0; /* Partial array self refresh config */ + + ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24); + debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2); +} + +/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ + +#if !defined(CONFIG_SYS_FSL_DDR1) +static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) +{ +#if CONFIG_DIMM_SLOTS_PER_CTLR == 1 + if (dimm_params[0].n_ranks == 4) + return 1; +#endif + +#if CONFIG_DIMM_SLOTS_PER_CTLR == 2 + if ((dimm_params[0].n_ranks == 2) && + (dimm_params[1].n_ranks == 2)) + return 1; + +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + if (dimm_params[0].n_ranks == 4) + return 1; +#endif +#endif + return 0; +} + +/* + * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0) + * + * Avoid writing for DDR I. The new PQ38 DDR controller + * dreams up non-zero default values to be backwards compatible. + */ +static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const dimm_params_t *dimm_params) +{ + unsigned char trwt_mclk = 0; /* Read-to-write turnaround */ + unsigned char twrt_mclk = 0; /* Write-to-read turnaround */ + /* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */ + unsigned char trrt_mclk = 0; /* Read-to-read turnaround */ + unsigned char twwt_mclk = 0; /* Write-to-write turnaround */ + + /* Active powerdown exit timing (tXARD and tXARDS). */ + unsigned char act_pd_exit_mclk; + /* Precharge powerdown exit timing (tXP). */ + unsigned char pre_pd_exit_mclk; + /* ODT powerdown exit timing (tAXPD). */ + unsigned char taxpd_mclk; + /* Mode register set cycle time (tMRD). */ + unsigned char tmrd_mclk; + +#ifdef CONFIG_SYS_FSL_DDR3 + /* + * (tXARD and tXARDS). Empirical? + * The DDR3 spec has not tXARD, + * we use the tXP instead of it. + * tXP=max(3nCK, 7.5ns) for DDR3. + * spec has not the tAXPD, we use + * tAXPD=1, need design to confirm. + */ + int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */ + unsigned int data_rate = get_ddr_freq(0); + tmrd_mclk = 4; + /* set the turnaround time */ + + /* + * for single quad-rank DIMM and two dual-rank DIMMs + * to avoid ODT overlap + */ + if (avoid_odt_overlap(dimm_params)) { + twwt_mclk = 2; + trrt_mclk = 1; + } + /* for faster clock, need more time for data setup */ + trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1; + + if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving)) + twrt_mclk = 1; + + if (popts->dynamic_power == 0) { /* powerdown is not used */ + act_pd_exit_mclk = 1; + pre_pd_exit_mclk = 1; + taxpd_mclk = 1; + } else { + /* act_pd_exit_mclk = tXARD, see above */ + act_pd_exit_mclk = picos_to_mclk(tXP); + /* Mode register MR0[A12] is '1' - fast exit */ + pre_pd_exit_mclk = act_pd_exit_mclk; + taxpd_mclk = 1; + } +#else /* CONFIG_SYS_FSL_DDR2 */ + /* + * (tXARD and tXARDS). Empirical? + * tXARD = 2 for DDR2 + * tXP=2 + * tAXPD=8 + */ + act_pd_exit_mclk = 2; + pre_pd_exit_mclk = 2; + taxpd_mclk = 8; + tmrd_mclk = 2; +#endif + + if (popts->trwt_override) + trwt_mclk = popts->trwt; + + ddr->timing_cfg_0 = (0 + | ((trwt_mclk & 0x3) << 30) /* RWT */ + | ((twrt_mclk & 0x3) << 28) /* WRT */ + | ((trrt_mclk & 0x3) << 26) /* RRT */ + | ((twwt_mclk & 0x3) << 24) /* WWT */ + | ((act_pd_exit_mclk & 0x7) << 20) /* ACT_PD_EXIT */ + | ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */ + | ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */ + | ((tmrd_mclk & 0xf) << 0) /* MRS_CYC */ + ); + debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); +} +#endif /* defined(CONFIG_SYS_FSL_DDR2) */ + +/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ +static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency) +{ + /* Extended precharge to activate interval (tRP) */ + unsigned int ext_pretoact = 0; + /* Extended Activate to precharge interval (tRAS) */ + unsigned int ext_acttopre = 0; + /* Extended activate to read/write interval (tRCD) */ + unsigned int ext_acttorw = 0; + /* Extended refresh recovery time (tRFC) */ + unsigned int ext_refrec; + /* Extended MCAS latency from READ cmd */ + unsigned int ext_caslat = 0; + /* Extended last data to precharge interval (tWR) */ + unsigned int ext_wrrec = 0; + /* Control Adjust */ + unsigned int cntl_adj = 0; + + ext_pretoact = picos_to_mclk(common_dimm->trp_ps) >> 4; + ext_acttopre = picos_to_mclk(common_dimm->tras_ps) >> 4; + ext_acttorw = picos_to_mclk(common_dimm->trcd_ps) >> 4; + ext_caslat = (2 * cas_latency - 1) >> 4; + ext_refrec = (picos_to_mclk(common_dimm->trfc_ps) - 8) >> 4; + /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ + ext_wrrec = (picos_to_mclk(common_dimm->twr_ps) + + (popts->otf_burst_chop_en ? 2 : 0)) >> 4; + + ddr->timing_cfg_3 = (0 + | ((ext_pretoact & 0x1) << 28) + | ((ext_acttopre & 0x3) << 24) + | ((ext_acttorw & 0x1) << 22) + | ((ext_refrec & 0x1F) << 16) + | ((ext_caslat & 0x3) << 12) + | ((ext_wrrec & 0x1) << 8) + | ((cntl_adj & 0x7) << 0) + ); + debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3); +} + +/* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */ +static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency) +{ + /* Precharge-to-activate interval (tRP) */ + unsigned char pretoact_mclk; + /* Activate to precharge interval (tRAS) */ + unsigned char acttopre_mclk; + /* Activate to read/write interval (tRCD) */ + unsigned char acttorw_mclk; + /* CASLAT */ + unsigned char caslat_ctrl; + /* Refresh recovery time (tRFC) ; trfc_low */ + unsigned char refrec_ctrl; + /* Last data to precharge minimum interval (tWR) */ + unsigned char wrrec_mclk; + /* Activate-to-activate interval (tRRD) */ + unsigned char acttoact_mclk; + /* Last write data pair to read command issue interval (tWTR) */ + unsigned char wrtord_mclk; + /* DDR_SDRAM_MODE doesn't support 9,11,13,15 */ + static const u8 wrrec_table[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0}; + + pretoact_mclk = picos_to_mclk(common_dimm->trp_ps); + acttopre_mclk = picos_to_mclk(common_dimm->tras_ps); + acttorw_mclk = picos_to_mclk(common_dimm->trcd_ps); + + /* + * Translate CAS Latency to a DDR controller field value: + * + * CAS Lat DDR I DDR II Ctrl + * Clocks SPD Bit SPD Bit Value + * ------- ------- ------- ----- + * 1.0 0 0001 + * 1.5 1 0010 + * 2.0 2 2 0011 + * 2.5 3 0100 + * 3.0 4 3 0101 + * 3.5 5 0110 + * 4.0 4 0111 + * 4.5 1000 + * 5.0 5 1001 + */ +#if defined(CONFIG_SYS_FSL_DDR1) + caslat_ctrl = (cas_latency + 1) & 0x07; +#elif defined(CONFIG_SYS_FSL_DDR2) + caslat_ctrl = 2 * cas_latency - 1; +#else + /* + * if the CAS latency more than 8 cycle, + * we need set extend bit for it at + * TIMING_CFG_3[EXT_CASLAT] + */ + caslat_ctrl = 2 * cas_latency - 1; +#endif + + refrec_ctrl = picos_to_mclk(common_dimm->trfc_ps) - 8; + wrrec_mclk = picos_to_mclk(common_dimm->twr_ps); + + if (wrrec_mclk > 16) + printf("Error: WRREC doesn't support more than 16 clocks\n"); + else + wrrec_mclk = wrrec_table[wrrec_mclk - 1]; + if (popts->otf_burst_chop_en) + wrrec_mclk += 2; + + acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps); + /* + * JEDEC has min requirement for tRRD + */ +#if defined(CONFIG_SYS_FSL_DDR3) + if (acttoact_mclk < 4) + acttoact_mclk = 4; +#endif + wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps); + /* + * JEDEC has some min requirements for tWTR + */ +#if defined(CONFIG_SYS_FSL_DDR2) + if (wrtord_mclk < 2) + wrtord_mclk = 2; +#elif defined(CONFIG_SYS_FSL_DDR3) + if (wrtord_mclk < 4) + wrtord_mclk = 4; +#endif + if (popts->otf_burst_chop_en) + wrtord_mclk += 2; + + ddr->timing_cfg_1 = (0 + | ((pretoact_mclk & 0x0F) << 28) + | ((acttopre_mclk & 0x0F) << 24) + | ((acttorw_mclk & 0xF) << 20) + | ((caslat_ctrl & 0xF) << 16) + | ((refrec_ctrl & 0xF) << 12) + | ((wrrec_mclk & 0x0F) << 8) + | ((acttoact_mclk & 0x0F) << 4) + | ((wrtord_mclk & 0x0F) << 0) + ); + debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); +} + +/* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */ +static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency, + unsigned int additive_latency) +{ + /* Additive latency */ + unsigned char add_lat_mclk; + /* CAS-to-preamble override */ + unsigned short cpo; + /* Write latency */ + unsigned char wr_lat; + /* Read to precharge (tRTP) */ + unsigned char rd_to_pre; + /* Write command to write data strobe timing adjustment */ + unsigned char wr_data_delay; + /* Minimum CKE pulse width (tCKE) */ + unsigned char cke_pls; + /* Window for four activates (tFAW) */ + unsigned short four_act; + + /* FIXME add check that this must be less than acttorw_mclk */ + add_lat_mclk = additive_latency; + cpo = popts->cpo_override; + +#if defined(CONFIG_SYS_FSL_DDR1) + /* + * This is a lie. It should really be 1, but if it is + * set to 1, bits overlap into the old controller's + * otherwise unused ACSM field. If we leave it 0, then + * the HW will magically treat it as 1 for DDR 1. Oh Yea. + */ + wr_lat = 0; +#elif defined(CONFIG_SYS_FSL_DDR2) + wr_lat = cas_latency - 1; +#else + wr_lat = compute_cas_write_latency(); +#endif + + rd_to_pre = picos_to_mclk(common_dimm->trtp_ps); + /* + * JEDEC has some min requirements for tRTP + */ +#if defined(CONFIG_SYS_FSL_DDR2) + if (rd_to_pre < 2) + rd_to_pre = 2; +#elif defined(CONFIG_SYS_FSL_DDR3) + if (rd_to_pre < 4) + rd_to_pre = 4; +#endif + if (additive_latency) + rd_to_pre += additive_latency; + if (popts->otf_burst_chop_en) + rd_to_pre += 2; /* according to UM */ + + wr_data_delay = popts->write_data_delay; + cke_pls = picos_to_mclk(popts->tcke_clock_pulse_width_ps); + four_act = picos_to_mclk(popts->tfaw_window_four_activates_ps); + + ddr->timing_cfg_2 = (0 + | ((add_lat_mclk & 0xf) << 28) + | ((cpo & 0x1f) << 23) + | ((wr_lat & 0xf) << 19) + | ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT) + | ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT) + | ((cke_pls & 0x7) << 6) + | ((four_act & 0x3f) << 0) + ); + debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); +} + +/* DDR SDRAM Register Control Word */ +static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm) +{ + if (common_dimm->all_dimms_registered && + !common_dimm->all_dimms_unbuffered) { + if (popts->rcw_override) { + ddr->ddr_sdram_rcw_1 = popts->rcw_1; + ddr->ddr_sdram_rcw_2 = popts->rcw_2; + } else { + ddr->ddr_sdram_rcw_1 = + common_dimm->rcw[0] << 28 | \ + common_dimm->rcw[1] << 24 | \ + common_dimm->rcw[2] << 20 | \ + common_dimm->rcw[3] << 16 | \ + common_dimm->rcw[4] << 12 | \ + common_dimm->rcw[5] << 8 | \ + common_dimm->rcw[6] << 4 | \ + common_dimm->rcw[7]; + ddr->ddr_sdram_rcw_2 = + common_dimm->rcw[8] << 28 | \ + common_dimm->rcw[9] << 24 | \ + common_dimm->rcw[10] << 20 | \ + common_dimm->rcw[11] << 16 | \ + common_dimm->rcw[12] << 12 | \ + common_dimm->rcw[13] << 8 | \ + common_dimm->rcw[14] << 4 | \ + common_dimm->rcw[15]; + } + debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1); + debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2); + } +} + +/* DDR SDRAM control configuration (DDR_SDRAM_CFG) */ +static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm) +{ + unsigned int mem_en; /* DDR SDRAM interface logic enable */ + unsigned int sren; /* Self refresh enable (during sleep) */ + unsigned int ecc_en; /* ECC enable. */ + unsigned int rd_en; /* Registered DIMM enable */ + unsigned int sdram_type; /* Type of SDRAM */ + unsigned int dyn_pwr; /* Dynamic power management mode */ + unsigned int dbw; /* DRAM dta bus width */ + unsigned int eight_be = 0; /* 8-beat burst enable, DDR2 is zero */ + unsigned int ncap = 0; /* Non-concurrent auto-precharge */ + unsigned int threet_en; /* Enable 3T timing */ + unsigned int twot_en; /* Enable 2T timing */ + unsigned int ba_intlv_ctl; /* Bank (CS) interleaving control */ + unsigned int x32_en = 0; /* x32 enable */ + unsigned int pchb8 = 0; /* precharge bit 8 enable */ + unsigned int hse; /* Global half strength override */ + unsigned int mem_halt = 0; /* memory controller halt */ + unsigned int bi = 0; /* Bypass initialization */ + + mem_en = 1; + sren = popts->self_refresh_in_sleep; + if (common_dimm->all_dimms_ecc_capable) { + /* Allow setting of ECC only if all DIMMs are ECC. */ + ecc_en = popts->ecc_mode; + } else { + ecc_en = 0; + } + + if (common_dimm->all_dimms_registered && + !common_dimm->all_dimms_unbuffered) { + rd_en = 1; + twot_en = 0; + } else { + rd_en = 0; + twot_en = popts->twot_en; + } + + sdram_type = CONFIG_FSL_SDRAM_TYPE; + + dyn_pwr = popts->dynamic_power; + dbw = popts->data_bus_width; + /* 8-beat burst enable DDR-III case + * we must clear it when use the on-the-fly mode, + * must set it when use the 32-bits bus mode. + */ + if (sdram_type == SDRAM_TYPE_DDR3) { + if (popts->burst_length == DDR_BL8) + eight_be = 1; + if (popts->burst_length == DDR_OTF) + eight_be = 0; + if (dbw == 0x1) + eight_be = 1; + } + + threet_en = popts->threet_en; + ba_intlv_ctl = popts->ba_intlv_ctl; + hse = popts->half_strength_driver_enable; + + ddr->ddr_sdram_cfg = (0 + | ((mem_en & 0x1) << 31) + | ((sren & 0x1) << 30) + | ((ecc_en & 0x1) << 29) + | ((rd_en & 0x1) << 28) + | ((sdram_type & 0x7) << 24) + | ((dyn_pwr & 0x1) << 21) + | ((dbw & 0x3) << 19) + | ((eight_be & 0x1) << 18) + | ((ncap & 0x1) << 17) + | ((threet_en & 0x1) << 16) + | ((twot_en & 0x1) << 15) + | ((ba_intlv_ctl & 0x7F) << 8) + | ((x32_en & 0x1) << 5) + | ((pchb8 & 0x1) << 4) + | ((hse & 0x1) << 3) + | ((mem_halt & 0x1) << 1) + | ((bi & 0x1) << 0) + ); + debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg); +} + +/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */ +static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const unsigned int unq_mrs_en) +{ + unsigned int frc_sr = 0; /* Force self refresh */ + unsigned int sr_ie = 0; /* Self-refresh interrupt enable */ + unsigned int dll_rst_dis; /* DLL reset disable */ + unsigned int dqs_cfg; /* DQS configuration */ + unsigned int odt_cfg = 0; /* ODT configuration */ + unsigned int num_pr; /* Number of posted refreshes */ + unsigned int slow = 0; /* DDR will be run less than 1250 */ + unsigned int x4_en = 0; /* x4 DRAM enable */ + unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */ + unsigned int ap_en; /* Address Parity Enable */ + unsigned int d_init; /* DRAM data initialization */ + unsigned int rcw_en = 0; /* Register Control Word Enable */ + unsigned int md_en = 0; /* Mirrored DIMM Enable */ + unsigned int qd_en = 0; /* quad-rank DIMM Enable */ + int i; + + dll_rst_dis = 1; /* Make this configurable */ + dqs_cfg = popts->dqs_config; + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (popts->cs_local_opts[i].odt_rd_cfg + || popts->cs_local_opts[i].odt_wr_cfg) { + odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; + break; + } + } + + num_pr = 1; /* Make this configurable */ + + /* + * 8572 manual says + * {TIMING_CFG_1[PRETOACT] + * + [DDR_SDRAM_CFG_2[NUM_PR] + * * ({EXT_REFREC || REFREC} + 8 + 2)]} + * << DDR_SDRAM_INTERVAL[REFINT] + */ +#if defined(CONFIG_SYS_FSL_DDR3) + obc_cfg = popts->otf_burst_chop_en; +#else + obc_cfg = 0; +#endif + +#if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7) + slow = get_ddr_freq(0) < 1249000000; +#endif + + if (popts->registered_dimm_en) { + rcw_en = 1; + ap_en = popts->ap_en; + } else { + ap_en = 0; + } + + x4_en = popts->x4_en ? 1 : 0; + +#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) + /* Use the DDR controller to auto initialize memory. */ + d_init = popts->ecc_init_using_memctl; + ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE; + debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init); +#else + /* Memory will be initialized via DMA, or not at all. */ + d_init = 0; +#endif + +#if defined(CONFIG_SYS_FSL_DDR3) + md_en = popts->mirrored_dimm; +#endif + qd_en = popts->quad_rank_present ? 1 : 0; + ddr->ddr_sdram_cfg_2 = (0 + | ((frc_sr & 0x1) << 31) + | ((sr_ie & 0x1) << 30) + | ((dll_rst_dis & 0x1) << 29) + | ((dqs_cfg & 0x3) << 26) + | ((odt_cfg & 0x3) << 21) + | ((num_pr & 0xf) << 12) + | ((slow & 1) << 11) + | (x4_en << 10) + | (qd_en << 9) + | (unq_mrs_en << 8) + | ((obc_cfg & 0x1) << 6) + | ((ap_en & 0x1) << 5) + | ((d_init & 0x1) << 4) + | ((rcw_en & 0x1) << 2) + | ((md_en & 0x1) << 0) + ); + debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2); +} + +/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ +static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + const unsigned int unq_mrs_en) +{ + unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */ + unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */ + +#if defined(CONFIG_SYS_FSL_DDR3) + int i; + unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */ + unsigned int srt = 0; /* self-refresh temerature, normal range */ + unsigned int asr = 0; /* auto self-refresh disable */ + unsigned int cwl = compute_cas_write_latency() - 5; + unsigned int pasr = 0; /* partial array self refresh disable */ + + if (popts->rtt_override) + rtt_wr = popts->rtt_wr_override_value; + else + rtt_wr = popts->cs_local_opts[0].odt_rtt_wr; + + if (common_dimm->extended_op_srt) + srt = common_dimm->extended_op_srt; + + esdmode2 = (0 + | ((rtt_wr & 0x3) << 9) + | ((srt & 0x1) << 7) + | ((asr & 0x1) << 6) + | ((cwl & 0x7) << 3) + | ((pasr & 0x7) << 0)); +#endif + ddr->ddr_sdram_mode_2 = (0 + | ((esdmode2 & 0xFFFF) << 16) + | ((esdmode3 & 0xFFFF) << 0) + ); + debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2); + +#ifdef CONFIG_SYS_FSL_DDR3 + if (unq_mrs_en) { /* unique mode registers are supported */ + for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (popts->rtt_override) + rtt_wr = popts->rtt_wr_override_value; + else + rtt_wr = popts->cs_local_opts[i].odt_rtt_wr; + + esdmode2 &= 0xF9FF; /* clear bit 10, 9 */ + esdmode2 |= (rtt_wr & 0x3) << 9; + switch (i) { + case 1: + ddr->ddr_sdram_mode_4 = (0 + | ((esdmode2 & 0xFFFF) << 16) + | ((esdmode3 & 0xFFFF) << 0) + ); + break; + case 2: + ddr->ddr_sdram_mode_6 = (0 + | ((esdmode2 & 0xFFFF) << 16) + | ((esdmode3 & 0xFFFF) << 0) + ); + break; + case 3: + ddr->ddr_sdram_mode_8 = (0 + | ((esdmode2 & 0xFFFF) << 16) + | ((esdmode3 & 0xFFFF) << 0) + ); + break; + } + } + debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n", + ddr->ddr_sdram_mode_4); + debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n", + ddr->ddr_sdram_mode_6); + debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n", + ddr->ddr_sdram_mode_8); + } +#endif +} + +/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */ +static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm) +{ + unsigned int refint; /* Refresh interval */ + unsigned int bstopre; /* Precharge interval */ + + refint = picos_to_mclk(common_dimm->refresh_rate_ps); + + bstopre = popts->bstopre; + + /* refint field used 0x3FFF in earlier controllers */ + ddr->ddr_sdram_interval = (0 + | ((refint & 0xFFFF) << 16) + | ((bstopre & 0x3FFF) << 0) + ); + debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval); +} + +#if defined(CONFIG_SYS_FSL_DDR3) +/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ +static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency, + unsigned int additive_latency, + const unsigned int unq_mrs_en) +{ + unsigned short esdmode; /* Extended SDRAM mode */ + unsigned short sdmode; /* SDRAM mode */ + + /* Mode Register - MR1 */ + unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */ + unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */ + unsigned int rtt; + unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */ + unsigned int al = 0; /* Posted CAS# additive latency (AL) */ + unsigned int dic = 0; /* Output driver impedance, 40ohm */ + unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), + 1=Disable (Test/Debug) */ + + /* Mode Register - MR0 */ + unsigned int dll_on; /* DLL control for precharge PD, 0=off, 1=on */ + unsigned int wr = 0; /* Write Recovery */ + unsigned int dll_rst; /* DLL Reset */ + unsigned int mode; /* Normal=0 or Test=1 */ + unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ + /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ + unsigned int bt; + unsigned int bl; /* BL: Burst Length */ + + unsigned int wr_mclk; + /* + * DDR_SDRAM_MODE doesn't support 9,11,13,15 + * Please refer JEDEC Standard No. 79-3E for Mode Register MR0 + * for this table + */ + static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; + + const unsigned int mclk_ps = get_memory_clk_period_ps(); + int i; + + if (popts->rtt_override) + rtt = popts->rtt_override_value; + else + rtt = popts->cs_local_opts[0].odt_rtt_norm; + + if (additive_latency == (cas_latency - 1)) + al = 1; + if (additive_latency == (cas_latency - 2)) + al = 2; + + if (popts->quad_rank_present) + dic = 1; /* output driver impedance 240/7 ohm */ + + /* + * The esdmode value will also be used for writing + * MR1 during write leveling for DDR3, although the + * bits specifically related to the write leveling + * scheme will be handled automatically by the DDR + * controller. so we set the wrlvl_en = 0 here. + */ + esdmode = (0 + | ((qoff & 0x1) << 12) + | ((tdqs_en & 0x1) << 11) + | ((rtt & 0x4) << 7) /* rtt field is split */ + | ((wrlvl_en & 0x1) << 7) + | ((rtt & 0x2) << 5) /* rtt field is split */ + | ((dic & 0x2) << 4) /* DIC field is split */ + | ((al & 0x3) << 3) + | ((rtt & 0x1) << 2) /* rtt field is split */ + | ((dic & 0x1) << 1) /* DIC field is split */ + | ((dll_en & 0x1) << 0) + ); + + /* + * DLL control for precharge PD + * 0=slow exit DLL off (tXPDLL) + * 1=fast exit DLL on (tXP) + */ + dll_on = 1; + + wr_mclk = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps; + if (wr_mclk <= 16) { + wr = wr_table[wr_mclk - 5]; + } else { + printf("Error: unsupported write recovery for mode register " + "wr_mclk = %d\n", wr_mclk); + } + + dll_rst = 0; /* dll no reset */ + mode = 0; /* normal mode */ + + /* look up table to get the cas latency bits */ + if (cas_latency >= 5 && cas_latency <= 16) { + unsigned char cas_latency_table[] = { + 0x2, /* 5 clocks */ + 0x4, /* 6 clocks */ + 0x6, /* 7 clocks */ + 0x8, /* 8 clocks */ + 0xa, /* 9 clocks */ + 0xc, /* 10 clocks */ + 0xe, /* 11 clocks */ + 0x1, /* 12 clocks */ + 0x3, /* 13 clocks */ + 0x5, /* 14 clocks */ + 0x7, /* 15 clocks */ + 0x9, /* 16 clocks */ + }; + caslat = cas_latency_table[cas_latency - 5]; + } else { + printf("Error: unsupported cas latency for mode register\n"); + } + + bt = 0; /* Nibble sequential */ + + switch (popts->burst_length) { + case DDR_BL8: + bl = 0; + break; + case DDR_OTF: + bl = 1; + break; + case DDR_BC4: + bl = 2; + break; + default: + printf("Error: invalid burst length of %u specified. " + " Defaulting to on-the-fly BC4 or BL8 beats.\n", + popts->burst_length); + bl = 1; + break; + } + + sdmode = (0 + | ((dll_on & 0x1) << 12) + | ((wr & 0x7) << 9) + | ((dll_rst & 0x1) << 8) + | ((mode & 0x1) << 7) + | (((caslat >> 1) & 0x7) << 4) + | ((bt & 0x1) << 3) + | ((caslat & 1) << 2) + | ((bl & 0x3) << 0) + ); + + ddr->ddr_sdram_mode = (0 + | ((esdmode & 0xFFFF) << 16) + | ((sdmode & 0xFFFF) << 0) + ); + + debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); + + if (unq_mrs_en) { /* unique mode registers are supported */ + for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (popts->rtt_override) + rtt = popts->rtt_override_value; + else + rtt = popts->cs_local_opts[i].odt_rtt_norm; + + esdmode &= 0xFDBB; /* clear bit 9,6,2 */ + esdmode |= (0 + | ((rtt & 0x4) << 7) /* rtt field is split */ + | ((rtt & 0x2) << 5) /* rtt field is split */ + | ((rtt & 0x1) << 2) /* rtt field is split */ + ); + switch (i) { + case 1: + ddr->ddr_sdram_mode_3 = (0 + | ((esdmode & 0xFFFF) << 16) + | ((sdmode & 0xFFFF) << 0) + ); + break; + case 2: + ddr->ddr_sdram_mode_5 = (0 + | ((esdmode & 0xFFFF) << 16) + | ((sdmode & 0xFFFF) << 0) + ); + break; + case 3: + ddr->ddr_sdram_mode_7 = (0 + | ((esdmode & 0xFFFF) << 16) + | ((sdmode & 0xFFFF) << 0) + ); + break; + } + } + debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n", + ddr->ddr_sdram_mode_3); + debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n", + ddr->ddr_sdram_mode_5); + debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n", + ddr->ddr_sdram_mode_5); + } +} + +#else /* !CONFIG_SYS_FSL_DDR3 */ + +/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ +static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm, + unsigned int cas_latency, + unsigned int additive_latency, + const unsigned int unq_mrs_en) +{ + unsigned short esdmode; /* Extended SDRAM mode */ + unsigned short sdmode; /* SDRAM mode */ + + /* + * FIXME: This ought to be pre-calculated in a + * technology-specific routine, + * e.g. compute_DDR2_mode_register(), and then the + * sdmode and esdmode passed in as part of common_dimm. + */ + + /* Extended Mode Register */ + unsigned int mrs = 0; /* Mode Register Set */ + unsigned int outputs = 0; /* 0=Enabled, 1=Disabled */ + unsigned int rdqs_en = 0; /* RDQS Enable: 0=no, 1=yes */ + unsigned int dqs_en = 0; /* DQS# Enable: 0=enable, 1=disable */ + unsigned int ocd = 0; /* 0x0=OCD not supported, + 0x7=OCD default state */ + unsigned int rtt; + unsigned int al; /* Posted CAS# additive latency (AL) */ + unsigned int ods = 0; /* Output Drive Strength: + 0 = Full strength (18ohm) + 1 = Reduced strength (4ohm) */ + unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), + 1=Disable (Test/Debug) */ + + /* Mode Register (MR) */ + unsigned int mr; /* Mode Register Definition */ + unsigned int pd; /* Power-Down Mode */ + unsigned int wr; /* Write Recovery */ + unsigned int dll_res; /* DLL Reset */ + unsigned int mode; /* Normal=0 or Test=1 */ + unsigned int caslat = 0;/* CAS# latency */ + /* BT: Burst Type (0=Sequential, 1=Interleaved) */ + unsigned int bt; + unsigned int bl; /* BL: Burst Length */ + +#if defined(CONFIG_SYS_FSL_DDR2) + const unsigned int mclk_ps = get_memory_clk_period_ps(); +#endif + dqs_en = !popts->dqs_config; + rtt = fsl_ddr_get_rtt(); + + al = additive_latency; + + esdmode = (0 + | ((mrs & 0x3) << 14) + | ((outputs & 0x1) << 12) + | ((rdqs_en & 0x1) << 11) + | ((dqs_en & 0x1) << 10) + | ((ocd & 0x7) << 7) + | ((rtt & 0x2) << 5) /* rtt field is split */ + | ((al & 0x7) << 3) + | ((rtt & 0x1) << 2) /* rtt field is split */ + | ((ods & 0x1) << 1) + | ((dll_en & 0x1) << 0) + ); + + mr = 0; /* FIXME: CHECKME */ + + /* + * 0 = Fast Exit (Normal) + * 1 = Slow Exit (Low Power) + */ + pd = 0; + +#if defined(CONFIG_SYS_FSL_DDR1) + wr = 0; /* Historical */ +#elif defined(CONFIG_SYS_FSL_DDR2) + wr = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps - 1; +#endif + dll_res = 0; + mode = 0; + +#if defined(CONFIG_SYS_FSL_DDR1) + if (1 <= cas_latency && cas_latency <= 4) { + unsigned char mode_caslat_table[4] = { + 0x5, /* 1.5 clocks */ + 0x2, /* 2.0 clocks */ + 0x6, /* 2.5 clocks */ + 0x3 /* 3.0 clocks */ + }; + caslat = mode_caslat_table[cas_latency - 1]; + } else { + printf("Warning: unknown cas_latency %d\n", cas_latency); + } +#elif defined(CONFIG_SYS_FSL_DDR2) + caslat = cas_latency; +#endif + bt = 0; + + switch (popts->burst_length) { + case DDR_BL4: + bl = 2; + break; + case DDR_BL8: + bl = 3; + break; + default: + printf("Error: invalid burst length of %u specified. " + " Defaulting to 4 beats.\n", + popts->burst_length); + bl = 2; + break; + } + + sdmode = (0 + | ((mr & 0x3) << 14) + | ((pd & 0x1) << 12) + | ((wr & 0x7) << 9) + | ((dll_res & 0x1) << 8) + | ((mode & 0x1) << 7) + | ((caslat & 0x7) << 4) + | ((bt & 0x1) << 3) + | ((bl & 0x7) << 0) + ); + + ddr->ddr_sdram_mode = (0 + | ((esdmode & 0xFFFF) << 16) + | ((sdmode & 0xFFFF) << 0) + ); + debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); +} +#endif + +/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */ +static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int init_value; /* Initialization value */ + +#ifdef CONFIG_MEM_INIT_VALUE + init_value = CONFIG_MEM_INIT_VALUE; +#else + init_value = 0xDEADBEEF; +#endif + ddr->ddr_data_init = init_value; +} + +/* + * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL) + * The old controller on the 8540/60 doesn't have this register. + * Hope it's OK to set it (to 0) anyway. + */ +static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts) +{ + unsigned int clk_adjust; /* Clock adjust */ + + clk_adjust = popts->clk_adjust; + ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23; + debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl); +} + +/* DDR Initialization Address (DDR_INIT_ADDR) */ +static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int init_addr = 0; /* Initialization address */ + + ddr->ddr_init_addr = init_addr; +} + +/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */ +static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int uia = 0; /* Use initialization address */ + unsigned int init_ext_addr = 0; /* Initialization address */ + + ddr->ddr_init_ext_addr = (0 + | ((uia & 0x1) << 31) + | (init_ext_addr & 0xF) + ); +} + +/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */ +static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts) +{ + unsigned int rwt = 0; /* Read-to-write turnaround for same CS */ + unsigned int wrt = 0; /* Write-to-read turnaround for same CS */ + unsigned int rrt = 0; /* Read-to-read turnaround for same CS */ + unsigned int wwt = 0; /* Write-to-write turnaround for same CS */ + unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */ + +#if defined(CONFIG_SYS_FSL_DDR3) + if (popts->burst_length == DDR_BL8) { + /* We set BL/2 for fixed BL8 */ + rrt = 0; /* BL/2 clocks */ + wwt = 0; /* BL/2 clocks */ + } else { + /* We need to set BL/2 + 2 to BC4 and OTF */ + rrt = 2; /* BL/2 + 2 clocks */ + wwt = 2; /* BL/2 + 2 clocks */ + } + dll_lock = 1; /* tDLLK = 512 clocks from spec */ +#endif + ddr->timing_cfg_4 = (0 + | ((rwt & 0xf) << 28) + | ((wrt & 0xf) << 24) + | ((rrt & 0xf) << 20) + | ((wwt & 0xf) << 16) + | (dll_lock & 0x3) + ); + debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4); +} + +/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */ +static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency) +{ + unsigned int rodt_on = 0; /* Read to ODT on */ + unsigned int rodt_off = 0; /* Read to ODT off */ + unsigned int wodt_on = 0; /* Write to ODT on */ + unsigned int wodt_off = 0; /* Write to ODT off */ + +#if defined(CONFIG_SYS_FSL_DDR3) + /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ + rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1; + rodt_off = 4; /* 4 clocks */ + wodt_on = 1; /* 1 clocks */ + wodt_off = 4; /* 4 clocks */ +#endif + + ddr->timing_cfg_5 = (0 + | ((rodt_on & 0x1f) << 24) + | ((rodt_off & 0x7) << 20) + | ((wodt_on & 0x1f) << 12) + | ((wodt_off & 0x7) << 8) + ); + debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5); +} + +/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */ +static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en) +{ + unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */ + /* Normal Operation Full Calibration Time (tZQoper) */ + unsigned int zqoper = 0; + /* Normal Operation Short Calibration Time (tZQCS) */ + unsigned int zqcs = 0; + + if (zq_en) { + zqinit = 9; /* 512 clocks */ + zqoper = 8; /* 256 clocks */ + zqcs = 6; /* 64 clocks */ + } + + ddr->ddr_zq_cntl = (0 + | ((zq_en & 0x1) << 31) + | ((zqinit & 0xF) << 24) + | ((zqoper & 0xF) << 16) + | ((zqcs & 0xF) << 8) + ); + debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl); +} + +/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */ +static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en, + const memctl_options_t *popts) +{ + /* + * First DQS pulse rising edge after margining mode + * is programmed (tWL_MRD) + */ + unsigned int wrlvl_mrd = 0; + /* ODT delay after margining mode is programmed (tWL_ODTEN) */ + unsigned int wrlvl_odten = 0; + /* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */ + unsigned int wrlvl_dqsen = 0; + /* WRLVL_SMPL: Write leveling sample time */ + unsigned int wrlvl_smpl = 0; + /* WRLVL_WLR: Write leveling repeition time */ + unsigned int wrlvl_wlr = 0; + /* WRLVL_START: Write leveling start time */ + unsigned int wrlvl_start = 0; + + /* suggest enable write leveling for DDR3 due to fly-by topology */ + if (wrlvl_en) { + /* tWL_MRD min = 40 nCK, we set it 64 */ + wrlvl_mrd = 0x6; + /* tWL_ODTEN 128 */ + wrlvl_odten = 0x7; + /* tWL_DQSEN min = 25 nCK, we set it 32 */ + wrlvl_dqsen = 0x5; + /* + * Write leveling sample time at least need 6 clocks + * higher than tWLO to allow enough time for progagation + * delay and sampling the prime data bits. + */ + wrlvl_smpl = 0xf; + /* + * Write leveling repetition time + * at least tWLO + 6 clocks clocks + * we set it 64 + */ + wrlvl_wlr = 0x6; + /* + * Write leveling start time + * The value use for the DQS_ADJUST for the first sample + * when write leveling is enabled. It probably needs to be + * overriden per platform. + */ + wrlvl_start = 0x8; + /* + * Override the write leveling sample and start time + * according to specific board + */ + if (popts->wrlvl_override) { + wrlvl_smpl = popts->wrlvl_sample; + wrlvl_start = popts->wrlvl_start; + } + } + + ddr->ddr_wrlvl_cntl = (0 + | ((wrlvl_en & 0x1) << 31) + | ((wrlvl_mrd & 0x7) << 24) + | ((wrlvl_odten & 0x7) << 20) + | ((wrlvl_dqsen & 0x7) << 16) + | ((wrlvl_smpl & 0xf) << 12) + | ((wrlvl_wlr & 0x7) << 8) + | ((wrlvl_start & 0x1F) << 0) + ); + debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl); + ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2; + debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2); + ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3; + debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3); + +} + +/* DDR Self Refresh Counter (DDR_SR_CNTR) */ +static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it) +{ + /* Self Refresh Idle Threshold */ + ddr->ddr_sr_cntr = (sr_it & 0xF) << 16; +} + +static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) +{ + if (popts->addr_hash) { + ddr->ddr_eor = 0x40000000; /* address hash enable */ + puts("Address hashing enabled.\n"); + } +} + +static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) +{ + ddr->ddr_cdr1 = popts->ddr_cdr1; + debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1); +} + +static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) +{ + ddr->ddr_cdr2 = popts->ddr_cdr2; + debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2); +} + +unsigned int +check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int res = 0; + + /* + * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are + * not set at the same time. + */ + if (ddr->ddr_sdram_cfg & 0x10000000 + && ddr->ddr_sdram_cfg & 0x00008000) { + printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] " + " should not be set at the same time.\n"); + res++; + } + + return res; +} + +unsigned int +compute_fsl_memctl_config_regs(const memctl_options_t *popts, + fsl_ddr_cfg_regs_t *ddr, + const common_timing_params_t *common_dimm, + const dimm_params_t *dimm_params, + unsigned int dbw_cap_adj, + unsigned int size_only) +{ + unsigned int i; + unsigned int cas_latency; + unsigned int additive_latency; + unsigned int sr_it; + unsigned int zq_en; + unsigned int wrlvl_en; + unsigned int ip_rev = 0; + unsigned int unq_mrs_en = 0; + int cs_en = 1; + + memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t)); + + if (common_dimm == NULL) { + printf("Error: subset DIMM params struct null pointer\n"); + return 1; + } + + /* + * Process overrides first. + * + * FIXME: somehow add dereated caslat to this + */ + cas_latency = (popts->cas_latency_override) + ? popts->cas_latency_override_value + : common_dimm->lowest_common_SPD_caslat; + + additive_latency = (popts->additive_latency_override) + ? popts->additive_latency_override_value + : common_dimm->additive_latency; + + sr_it = (popts->auto_self_refresh_en) + ? popts->sr_it + : 0; + /* ZQ calibration */ + zq_en = (popts->zq_en) ? 1 : 0; + /* write leveling */ + wrlvl_en = (popts->wrlvl_en) ? 1 : 0; + + /* Chip Select Memory Bounds (CSn_BNDS) */ + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + unsigned long long ea, sa; + unsigned int cs_per_dimm + = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR; + unsigned int dimm_number + = i / cs_per_dimm; + unsigned long long rank_density + = dimm_params[dimm_number].rank_density >> dbw_cap_adj; + + if (dimm_params[dimm_number].n_ranks == 0) { + debug("Skipping setup of CS%u " + "because n_ranks on DIMM %u is 0\n", i, dimm_number); + continue; + } + if (popts->memctl_interleaving) { + switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + break; + case FSL_DDR_CS0_CS1: + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + if (i > 1) + cs_en = 0; + break; + case FSL_DDR_CS2_CS3: + default: + if (i > 0) + cs_en = 0; + break; + } + sa = common_dimm->base_address; + ea = sa + common_dimm->total_mem - 1; + } else if (!popts->memctl_interleaving) { + /* + * If memory interleaving between controllers is NOT + * enabled, the starting address for each memory + * controller is distinct. However, because rank + * interleaving is enabled, the starting and ending + * addresses of the total memory on that memory + * controller needs to be programmed into its + * respective CS0_BNDS. + */ + switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + sa = common_dimm->base_address; + ea = sa + common_dimm->total_mem - 1; + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + if ((i >= 2) && (dimm_number == 0)) { + sa = dimm_params[dimm_number].base_address + + 2 * rank_density; + ea = sa + 2 * rank_density - 1; + } else { + sa = dimm_params[dimm_number].base_address; + ea = sa + 2 * rank_density - 1; + } + break; + case FSL_DDR_CS0_CS1: + if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { + sa = dimm_params[dimm_number].base_address; + ea = sa + rank_density - 1; + if (i != 1) + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; + } else { + sa = 0; + ea = 0; + } + if (i == 0) + ea += rank_density; + break; + case FSL_DDR_CS2_CS3: + if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { + sa = dimm_params[dimm_number].base_address; + ea = sa + rank_density - 1; + if (i != 3) + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; + } else { + sa = 0; + ea = 0; + } + if (i == 2) + ea += (rank_density >> dbw_cap_adj); + break; + default: /* No bank(chip-select) interleaving */ + sa = dimm_params[dimm_number].base_address; + ea = sa + rank_density - 1; + if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) { + sa += (i % cs_per_dimm) * rank_density; + ea += (i % cs_per_dimm) * rank_density; + } else { + sa = 0; + ea = 0; + } + break; + } + } + + sa >>= 24; + ea >>= 24; + + if (cs_en) { + ddr->cs[i].bnds = (0 + | ((sa & 0xFFF) << 16)/* starting address MSB */ + | ((ea & 0xFFF) << 0) /* ending address MSB */ + ); + } else { + /* setting bnds to 0xffffffff for inactive CS */ + ddr->cs[i].bnds = 0xffffffff; + } + + debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds); + set_csn_config(dimm_number, i, ddr, popts, dimm_params); + set_csn_config_2(i, ddr); + } + + /* + * In the case we only need to compute the ddr sdram size, we only need + * to set csn registers, so return from here. + */ + if (size_only) + return 0; + + set_ddr_eor(ddr, popts); + +#if !defined(CONFIG_SYS_FSL_DDR1) + set_timing_cfg_0(ddr, popts, dimm_params); +#endif + + set_timing_cfg_3(ddr, popts, common_dimm, cas_latency); + set_timing_cfg_1(ddr, popts, common_dimm, cas_latency); + set_timing_cfg_2(ddr, popts, common_dimm, + cas_latency, additive_latency); + + set_ddr_cdr1(ddr, popts); + set_ddr_cdr2(ddr, popts); + set_ddr_sdram_cfg(ddr, popts, common_dimm); + ip_rev = fsl_ddr_get_version(); + if (ip_rev > 0x40400) + unq_mrs_en = 1; + + set_ddr_sdram_cfg_2(ddr, popts, unq_mrs_en); + set_ddr_sdram_mode(ddr, popts, common_dimm, + cas_latency, additive_latency, unq_mrs_en); + set_ddr_sdram_mode_2(ddr, popts, common_dimm, unq_mrs_en); + set_ddr_sdram_interval(ddr, popts, common_dimm); + set_ddr_data_init(ddr); + set_ddr_sdram_clk_cntl(ddr, popts); + set_ddr_init_addr(ddr); + set_ddr_init_ext_addr(ddr); + set_timing_cfg_4(ddr, popts); + set_timing_cfg_5(ddr, cas_latency); + + set_ddr_zq_cntl(ddr, zq_en); + set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts); + + set_ddr_sr_cntr(ddr, sr_it); + + set_ddr_sdram_rcw(ddr, popts, common_dimm); + +#ifdef CONFIG_SYS_FSL_DDR_EMU + /* disble DDR training for emulator */ + ddr->debug[2] = 0x00000400; + ddr->debug[4] = 0xff800000; +#endif + return check_fsl_memctl_config_regs(ddr); +} diff --git a/drivers/ddr/fsl/ddr1_dimm_params.c b/drivers/ddr/fsl/ddr1_dimm_params.c new file mode 100644 index 0000000000..7df27b90b7 --- /dev/null +++ b/drivers/ddr/fsl/ddr1_dimm_params.c @@ -0,0 +1,343 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include + +#include + +/* + * Calculate the Density of each Physical Rank. + * Returned size is in bytes. + * + * Study these table from Byte 31 of JEDEC SPD Spec. + * + * DDR I DDR II + * Bit Size Size + * --- ----- ------ + * 7 high 512MB 512MB + * 6 256MB 256MB + * 5 128MB 128MB + * 4 64MB 16GB + * 3 32MB 8GB + * 2 16MB 4GB + * 1 2GB 2GB + * 0 low 1GB 1GB + * + * Reorder Table to be linear by stripping the bottom + * 2 or 5 bits off and shifting them up to the top. + */ + +static unsigned long long +compute_ranksize(unsigned int mem_type, unsigned char row_dens) +{ + unsigned long long bsize; + + /* Bottom 2 bits up to the top. */ + bsize = ((row_dens >> 2) | ((row_dens & 3) << 6)); + bsize <<= 24ULL; + debug("DDR: DDR I rank density = 0x%16llx\n", bsize); + + return bsize; +} + +/* + * Convert a two-nibble BCD value into a cycle time. + * While the spec calls for nano-seconds, picos are returned. + * + * This implements the tables for bytes 9, 23 and 25 for both + * DDR I and II. No allowance for distinguishing the invalid + * fields absent for DDR I yet present in DDR II is made. + * (That is, cycle times of .25, .33, .66 and .75 ns are + * allowed for both DDR II and I.) + */ +static unsigned int +convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) +{ + /* Table look up the lower nibble, allow DDR I & II. */ + unsigned int tenths_ps[16] = { + 0, + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 250, /* This and the next 3 entries valid ... */ + 330, /* ... only for tCK calculations. */ + 660, + 750, + 0, /* undefined */ + 0 /* undefined */ + }; + + unsigned int whole_ns = (spd_val & 0xF0) >> 4; + unsigned int tenth_ns = spd_val & 0x0F; + unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns]; + + return ps; +} + +static unsigned int +convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val) +{ + unsigned int tenth_ns = (spd_val & 0xF0) >> 4; + unsigned int hundredth_ns = spd_val & 0x0F; + unsigned int ps = tenth_ns * 100 + hundredth_ns * 10; + + return ps; +} + +static unsigned int byte40_table_ps[8] = { + 0, + 250, + 330, + 500, + 660, + 750, + 0, /* supposed to be RFC, but not sure what that means */ + 0 /* Undefined */ +}; + +static unsigned int +compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc) +{ + unsigned int trfc_ps; + + trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000 + + byte40_table_ps[(trctrfc_ext >> 1) & 0x7]; + + return trfc_ps; +} + +static unsigned int +compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc) +{ + unsigned int trc_ps; + + trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7]; + + return trc_ps; +} + +/* + * tCKmax from DDR I SPD Byte 43 + * + * Bits 7:2 == whole ns + * Bits 1:0 == quarter ns + * 00 == 0.00 ns + * 01 == 0.25 ns + * 10 == 0.50 ns + * 11 == 0.75 ns + * + * Returns picoseconds. + */ +static unsigned int +compute_tckmax_from_spd_ps(unsigned int byte43) +{ + return (byte43 >> 2) * 1000 + (byte43 & 0x3) * 250; +} + +/* + * Determine Refresh Rate. Ignore self refresh bit on DDR I. + * Table from SPD Spec, Byte 12, converted to picoseconds and + * filled in with "default" normal values. + */ +static unsigned int +determine_refresh_rate_ps(const unsigned int spd_refresh) +{ + unsigned int refresh_time_ps[8] = { + 15625000, /* 0 Normal 1.00x */ + 3900000, /* 1 Reduced .25x */ + 7800000, /* 2 Extended .50x */ + 31300000, /* 3 Extended 2.00x */ + 62500000, /* 4 Extended 4.00x */ + 125000000, /* 5 Extended 8.00x */ + 15625000, /* 6 Normal 1.00x filler */ + 15625000, /* 7 Normal 1.00x filler */ + }; + + return refresh_time_ps[spd_refresh & 0x7]; +} + +/* + * The purpose of this function is to compute a suitable + * CAS latency given the DRAM clock period. The SPD only + * defines at most 3 CAS latencies. Typically the slower in + * frequency the DIMM runs at, the shorter its CAS latency can be. + * If the DIMM is operating at a sufficiently low frequency, + * it may be able to run at a CAS latency shorter than the + * shortest SPD-defined CAS latency. + * + * If a CAS latency is not found, 0 is returned. + * + * Do this by finding in the standard speed bin table the longest + * tCKmin that doesn't exceed the value of mclk_ps (tCK). + * + * An assumption made is that the SDRAM device allows the + * CL to be programmed for a value that is lower than those + * advertised by the SPD. This is not always the case, + * as those modes not defined in the SPD are optional. + * + * CAS latency de-rating based upon values JEDEC Standard No. 79-E + * Table 11. + * + * ordinal 2, ddr1_speed_bins[1] contains tCK for CL=2 + */ + /* CL2.0 CL2.5 CL3.0 */ +unsigned short ddr1_speed_bins[] = {0, 7500, 6000, 5000 }; + +unsigned int +compute_derated_DDR1_CAS_latency(unsigned int mclk_ps) +{ + const unsigned int num_speed_bins = ARRAY_SIZE(ddr1_speed_bins); + unsigned int lowest_tCKmin_found = 0; + unsigned int lowest_tCKmin_CL = 0; + unsigned int i; + + debug("mclk_ps = %u\n", mclk_ps); + + for (i = 0; i < num_speed_bins; i++) { + unsigned int x = ddr1_speed_bins[i]; + debug("i=%u, x = %u, lowest_tCKmin_found = %u\n", + i, x, lowest_tCKmin_found); + if (x && lowest_tCKmin_found <= x && x <= mclk_ps) { + lowest_tCKmin_found = x; + lowest_tCKmin_CL = i + 1; + } + } + + debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL); + + return lowest_tCKmin_CL; +} + +/* + * ddr_compute_dimm_parameters for DDR1 SPD + * + * Compute DIMM parameters based upon the SPD information in spd. + * Writes the results to the dimm_params_t structure pointed by pdimm. + * + * FIXME: use #define for the retvals + */ +unsigned int +ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) +{ + unsigned int retval; + + if (spd->mem_type) { + if (spd->mem_type != SPD_MEMTYPE_DDR) { + printf("DIMM %u: is not a DDR1 SPD.\n", dimm_number); + return 1; + } + } else { + memset(pdimm, 0, sizeof(dimm_params_t)); + return 1; + } + + retval = ddr1_spd_check(spd); + if (retval) { + printf("DIMM %u: failed checksum\n", dimm_number); + return 2; + } + + /* + * The part name in ASCII in the SPD EEPROM is not null terminated. + * Guarantee null termination here by presetting all bytes to 0 + * and copying the part name in ASCII from the SPD onto it + */ + memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + + /* DIMM organization parameters */ + pdimm->n_ranks = spd->nrows; + pdimm->rank_density = compute_ranksize(spd->mem_type, spd->bank_dens); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + pdimm->data_width = spd->dataw_lsb; + pdimm->primary_sdram_width = spd->primw; + pdimm->ec_sdram_width = spd->ecw; + + /* + * FIXME: Need to determine registered_dimm status. + * 1 == register buffered + * 0 == unbuffered + */ + pdimm->registered_dimm = 0; /* unbuffered */ + + /* SDRAM device parameters */ + pdimm->n_row_addr = spd->nrow_addr; + pdimm->n_col_addr = spd->ncol_addr; + pdimm->n_banks_per_sdram_device = spd->nbanks; + pdimm->edc_config = spd->config; + pdimm->burst_lengths_bitmask = spd->burstl; + pdimm->row_density = spd->bank_dens; + + /* + * Calculate the Maximum Data Rate based on the Minimum Cycle time. + * The SPD clk_cycle field (tCKmin) is measured in tenths of + * nanoseconds and represented as BCD. + */ + pdimm->tckmin_x_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle); + pdimm->tckmin_x_minus_1_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2); + pdimm->tckmin_x_minus_2_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3); + + pdimm->tckmax_ps = compute_tckmax_from_spd_ps(spd->tckmax); + + /* + * Compute CAS latencies defined by SPD + * The SPD caslat_x should have at least 1 and at most 3 bits set. + * + * If cas_lat after masking is 0, the __ilog2 function returns + * 255 into the variable. This behavior is abused once. + */ + pdimm->caslat_x = __ilog2(spd->cas_lat); + pdimm->caslat_x_minus_1 = __ilog2(spd->cas_lat + & ~(1 << pdimm->caslat_x)); + pdimm->caslat_x_minus_2 = __ilog2(spd->cas_lat + & ~(1 << pdimm->caslat_x) + & ~(1 << pdimm->caslat_x_minus_1)); + + /* Compute CAS latencies below that defined by SPD */ + pdimm->caslat_lowest_derated + = compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps()); + + /* Compute timing parameters */ + pdimm->trcd_ps = spd->trcd * 250; + pdimm->trp_ps = spd->trp * 250; + pdimm->tras_ps = spd->tras * 1000; + + pdimm->twr_ps = mclk_to_picos(3); + pdimm->twtr_ps = mclk_to_picos(1); + pdimm->trfc_ps = compute_trfc_ps_from_spd(0, spd->trfc); + + pdimm->trrd_ps = spd->trrd * 250; + pdimm->trc_ps = compute_trc_ps_from_spd(0, spd->trc); + + pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh); + + pdimm->tis_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup); + pdimm->tih_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold); + pdimm->tds_ps + = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup); + pdimm->tdh_ps + = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); + + pdimm->trtp_ps = mclk_to_picos(2); /* By the book. */ + pdimm->tdqsq_max_ps = spd->tdqsq * 10; + pdimm->tqhs_ps = spd->tqhs * 10; + + return 0; +} diff --git a/drivers/ddr/fsl/ddr2_dimm_params.c b/drivers/ddr/fsl/ddr2_dimm_params.c new file mode 100644 index 0000000000..d865df78a8 --- /dev/null +++ b/drivers/ddr/fsl/ddr2_dimm_params.c @@ -0,0 +1,342 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include + +#include +/* + * Calculate the Density of each Physical Rank. + * Returned size is in bytes. + * + * Study these table from Byte 31 of JEDEC SPD Spec. + * + * DDR I DDR II + * Bit Size Size + * --- ----- ------ + * 7 high 512MB 512MB + * 6 256MB 256MB + * 5 128MB 128MB + * 4 64MB 16GB + * 3 32MB 8GB + * 2 16MB 4GB + * 1 2GB 2GB + * 0 low 1GB 1GB + * + * Reorder Table to be linear by stripping the bottom + * 2 or 5 bits off and shifting them up to the top. + * + */ +static unsigned long long +compute_ranksize(unsigned int mem_type, unsigned char row_dens) +{ + unsigned long long bsize; + + /* Bottom 5 bits up to the top. */ + bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)); + bsize <<= 27ULL; + debug("DDR: DDR II rank density = 0x%16llx\n", bsize); + + return bsize; +} + +/* + * Convert a two-nibble BCD value into a cycle time. + * While the spec calls for nano-seconds, picos are returned. + * + * This implements the tables for bytes 9, 23 and 25 for both + * DDR I and II. No allowance for distinguishing the invalid + * fields absent for DDR I yet present in DDR II is made. + * (That is, cycle times of .25, .33, .66 and .75 ns are + * allowed for both DDR II and I.) + */ +static unsigned int +convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) +{ + /* Table look up the lower nibble, allow DDR I & II. */ + unsigned int tenths_ps[16] = { + 0, + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 250, /* This and the next 3 entries valid ... */ + 330, /* ... only for tCK calculations. */ + 660, + 750, + 0, /* undefined */ + 0 /* undefined */ + }; + + unsigned int whole_ns = (spd_val & 0xF0) >> 4; + unsigned int tenth_ns = spd_val & 0x0F; + unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns]; + + return ps; +} + +static unsigned int +convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val) +{ + unsigned int tenth_ns = (spd_val & 0xF0) >> 4; + unsigned int hundredth_ns = spd_val & 0x0F; + unsigned int ps = tenth_ns * 100 + hundredth_ns * 10; + + return ps; +} + +static unsigned int byte40_table_ps[8] = { + 0, + 250, + 330, + 500, + 660, + 750, + 0, /* supposed to be RFC, but not sure what that means */ + 0 /* Undefined */ +}; + +static unsigned int +compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc) +{ + unsigned int trfc_ps; + + trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000 + + byte40_table_ps[(trctrfc_ext >> 1) & 0x7]; + + return trfc_ps; +} + +static unsigned int +compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc) +{ + unsigned int trc_ps; + + trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7]; + + return trc_ps; +} + +/* + * Determine Refresh Rate. Ignore self refresh bit on DDR I. + * Table from SPD Spec, Byte 12, converted to picoseconds and + * filled in with "default" normal values. + */ +static unsigned int +determine_refresh_rate_ps(const unsigned int spd_refresh) +{ + unsigned int refresh_time_ps[8] = { + 15625000, /* 0 Normal 1.00x */ + 3900000, /* 1 Reduced .25x */ + 7800000, /* 2 Extended .50x */ + 31300000, /* 3 Extended 2.00x */ + 62500000, /* 4 Extended 4.00x */ + 125000000, /* 5 Extended 8.00x */ + 15625000, /* 6 Normal 1.00x filler */ + 15625000, /* 7 Normal 1.00x filler */ + }; + + return refresh_time_ps[spd_refresh & 0x7]; +} + +/* + * The purpose of this function is to compute a suitable + * CAS latency given the DRAM clock period. The SPD only + * defines at most 3 CAS latencies. Typically the slower in + * frequency the DIMM runs at, the shorter its CAS latency can. + * be. If the DIMM is operating at a sufficiently low frequency, + * it may be able to run at a CAS latency shorter than the + * shortest SPD-defined CAS latency. + * + * If a CAS latency is not found, 0 is returned. + * + * Do this by finding in the standard speed bin table the longest + * tCKmin that doesn't exceed the value of mclk_ps (tCK). + * + * An assumption made is that the SDRAM device allows the + * CL to be programmed for a value that is lower than those + * advertised by the SPD. This is not always the case, + * as those modes not defined in the SPD are optional. + * + * CAS latency de-rating based upon values JEDEC Standard No. 79-2C + * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS, + * and tRC for corresponding bin" + * + * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3 + * Not certain if any good value exists for CL=2 + */ + /* CL2 CL3 CL4 CL5 CL6 CL7*/ +unsigned short ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500, 1875 }; + +unsigned int +compute_derated_DDR2_CAS_latency(unsigned int mclk_ps) +{ + const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins); + unsigned int lowest_tCKmin_found = 0; + unsigned int lowest_tCKmin_CL = 0; + unsigned int i; + + debug("mclk_ps = %u\n", mclk_ps); + + for (i = 0; i < num_speed_bins; i++) { + unsigned int x = ddr2_speed_bins[i]; + debug("i=%u, x = %u, lowest_tCKmin_found = %u\n", + i, x, lowest_tCKmin_found); + if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) { + lowest_tCKmin_found = x; + lowest_tCKmin_CL = i + 2; + } + } + + debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL); + + return lowest_tCKmin_CL; +} + +/* + * ddr_compute_dimm_parameters for DDR2 SPD + * + * Compute DIMM parameters based upon the SPD information in spd. + * Writes the results to the dimm_params_t structure pointed by pdimm. + * + * FIXME: use #define for the retvals + */ +unsigned int +ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) +{ + unsigned int retval; + + if (spd->mem_type) { + if (spd->mem_type != SPD_MEMTYPE_DDR2) { + printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number); + return 1; + } + } else { + memset(pdimm, 0, sizeof(dimm_params_t)); + return 1; + } + + retval = ddr2_spd_check(spd); + if (retval) { + printf("DIMM %u: failed checksum\n", dimm_number); + return 2; + } + + /* + * The part name in ASCII in the SPD EEPROM is not null terminated. + * Guarantee null termination here by presetting all bytes to 0 + * and copying the part name in ASCII from the SPD onto it + */ + memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + + /* DIMM organization parameters */ + pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1; + pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + pdimm->data_width = spd->dataw; + pdimm->primary_sdram_width = spd->primw; + pdimm->ec_sdram_width = spd->ecw; + + /* These are all the types defined by the JEDEC DDR2 SPD 1.3 spec */ + switch (spd->dimm_type) { + case DDR2_SPD_DIMMTYPE_RDIMM: + case DDR2_SPD_DIMMTYPE_72B_SO_RDIMM: + case DDR2_SPD_DIMMTYPE_MINI_RDIMM: + /* Registered/buffered DIMMs */ + pdimm->registered_dimm = 1; + break; + + case DDR2_SPD_DIMMTYPE_UDIMM: + case DDR2_SPD_DIMMTYPE_SO_DIMM: + case DDR2_SPD_DIMMTYPE_MICRO_DIMM: + case DDR2_SPD_DIMMTYPE_MINI_UDIMM: + /* Unbuffered DIMMs */ + pdimm->registered_dimm = 0; + break; + + case DDR2_SPD_DIMMTYPE_72B_SO_CDIMM: + default: + printf("unknown dimm_type 0x%02X\n", spd->dimm_type); + return 1; + } + + /* SDRAM device parameters */ + pdimm->n_row_addr = spd->nrow_addr; + pdimm->n_col_addr = spd->ncol_addr; + pdimm->n_banks_per_sdram_device = spd->nbanks; + pdimm->edc_config = spd->config; + pdimm->burst_lengths_bitmask = spd->burstl; + pdimm->row_density = spd->rank_dens; + + /* + * Calculate the Maximum Data Rate based on the Minimum Cycle time. + * The SPD clk_cycle field (tCKmin) is measured in tenths of + * nanoseconds and represented as BCD. + */ + pdimm->tckmin_x_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle); + pdimm->tckmin_x_minus_1_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2); + pdimm->tckmin_x_minus_2_ps + = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3); + + pdimm->tckmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax); + + /* + * Compute CAS latencies defined by SPD + * The SPD caslat_x should have at least 1 and at most 3 bits set. + * + * If cas_lat after masking is 0, the __ilog2 function returns + * 255 into the variable. This behavior is abused once. + */ + pdimm->caslat_x = __ilog2(spd->cas_lat); + pdimm->caslat_x_minus_1 = __ilog2(spd->cas_lat + & ~(1 << pdimm->caslat_x)); + pdimm->caslat_x_minus_2 = __ilog2(spd->cas_lat + & ~(1 << pdimm->caslat_x) + & ~(1 << pdimm->caslat_x_minus_1)); + + /* Compute CAS latencies below that defined by SPD */ + pdimm->caslat_lowest_derated + = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps()); + + /* Compute timing parameters */ + pdimm->trcd_ps = spd->trcd * 250; + pdimm->trp_ps = spd->trp * 250; + pdimm->tras_ps = spd->tras * 1000; + + pdimm->twr_ps = spd->twr * 250; + pdimm->twtr_ps = spd->twtr * 250; + pdimm->trfc_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc); + + pdimm->trrd_ps = spd->trrd * 250; + pdimm->trc_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc); + + pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh); + + pdimm->tis_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup); + pdimm->tih_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold); + pdimm->tds_ps + = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup); + pdimm->tdh_ps + = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); + + pdimm->trtp_ps = spd->trtp * 250; + pdimm->tdqsq_max_ps = spd->tdqsq * 10; + pdimm->tqhs_ps = spd->tqhs * 10; + + return 0; +} diff --git a/drivers/ddr/fsl/ddr3_dimm_params.c b/drivers/ddr/fsl/ddr3_dimm_params.c new file mode 100644 index 0000000000..a4b8c101f5 --- /dev/null +++ b/drivers/ddr/fsl/ddr3_dimm_params.c @@ -0,0 +1,341 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * Dave Liu + * + * calculate the organization and timing parameter + * from ddr3 spd, please refer to the spec + * JEDEC standard No.21-C 4_01_02_11R18.pdf + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include + +#include + +/* + * Calculate the Density of each Physical Rank. + * Returned size is in bytes. + * + * each rank size = + * sdram capacity(bit) / 8 * primary bus width / sdram width + * + * where: sdram capacity = spd byte4[3:0] + * primary bus width = spd byte8[2:0] + * sdram width = spd byte7[2:0] + * + * SPD byte4 - sdram density and banks + * bit[3:0] size(bit) size(byte) + * 0000 256Mb 32MB + * 0001 512Mb 64MB + * 0010 1Gb 128MB + * 0011 2Gb 256MB + * 0100 4Gb 512MB + * 0101 8Gb 1GB + * 0110 16Gb 2GB + * + * SPD byte8 - module memory bus width + * bit[2:0] primary bus width + * 000 8bits + * 001 16bits + * 010 32bits + * 011 64bits + * + * SPD byte7 - module organiztion + * bit[2:0] sdram device width + * 000 4bits + * 001 8bits + * 010 16bits + * 011 32bits + * + */ +static unsigned long long +compute_ranksize(const ddr3_spd_eeprom_t *spd) +{ + unsigned long long bsize; + + int nbit_sdram_cap_bsize = 0; + int nbit_primary_bus_width = 0; + int nbit_sdram_width = 0; + + if ((spd->density_banks & 0xf) < 7) + nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28; + if ((spd->bus_width & 0x7) < 4) + nbit_primary_bus_width = (spd->bus_width & 0x7) + 3; + if ((spd->organization & 0x7) < 4) + nbit_sdram_width = (spd->organization & 0x7) + 2; + + bsize = 1ULL << (nbit_sdram_cap_bsize - 3 + + nbit_primary_bus_width - nbit_sdram_width); + + debug("DDR: DDR III rank density = 0x%16llx\n", bsize); + + return bsize; +} + +/* + * ddr_compute_dimm_parameters for DDR3 SPD + * + * Compute DIMM parameters based upon the SPD information in spd. + * Writes the results to the dimm_params_t structure pointed by pdimm. + * + */ +unsigned int +ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) +{ + unsigned int retval; + unsigned int mtb_ps; + int ftb_10th_ps; + int i; + + if (spd->mem_type) { + if (spd->mem_type != SPD_MEMTYPE_DDR3) { + printf("DIMM %u: is not a DDR3 SPD.\n", dimm_number); + return 1; + } + } else { + memset(pdimm, 0, sizeof(dimm_params_t)); + return 1; + } + + retval = ddr3_spd_check(spd); + if (retval) { + printf("DIMM %u: failed checksum\n", dimm_number); + return 2; + } + + /* + * The part name in ASCII in the SPD EEPROM is not null terminated. + * Guarantee null termination here by presetting all bytes to 0 + * and copying the part name in ASCII from the SPD onto it + */ + memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); + if ((spd->info_size_crc & 0xF) > 1) + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + + /* DIMM organization parameters */ + pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; + pdimm->rank_density = compute_ranksize(spd); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); + if ((spd->bus_width >> 3) & 0x3) + pdimm->ec_sdram_width = 8; + else + pdimm->ec_sdram_width = 0; + pdimm->data_width = pdimm->primary_sdram_width + + pdimm->ec_sdram_width; + pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); + + /* These are the types defined by the JEDEC DDR3 SPD spec */ + pdimm->mirrored_dimm = 0; + pdimm->registered_dimm = 0; + switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) { + case DDR3_SPD_MODULETYPE_RDIMM: + case DDR3_SPD_MODULETYPE_MINI_RDIMM: + case DDR3_SPD_MODULETYPE_72B_SO_RDIMM: + /* Registered/buffered DIMMs */ + pdimm->registered_dimm = 1; + for (i = 0; i < 16; i += 2) { + u8 rcw = spd->mod_section.registered.rcw[i/2]; + pdimm->rcw[i] = (rcw >> 0) & 0x0F; + pdimm->rcw[i+1] = (rcw >> 4) & 0x0F; + } + break; + + case DDR3_SPD_MODULETYPE_UDIMM: + case DDR3_SPD_MODULETYPE_SO_DIMM: + case DDR3_SPD_MODULETYPE_MICRO_DIMM: + case DDR3_SPD_MODULETYPE_MINI_UDIMM: + case DDR3_SPD_MODULETYPE_MINI_CDIMM: + case DDR3_SPD_MODULETYPE_72B_SO_UDIMM: + case DDR3_SPD_MODULETYPE_72B_SO_CDIMM: + case DDR3_SPD_MODULETYPE_LRDIMM: + case DDR3_SPD_MODULETYPE_16B_SO_DIMM: + case DDR3_SPD_MODULETYPE_32B_SO_DIMM: + /* Unbuffered DIMMs */ + if (spd->mod_section.unbuffered.addr_mapping & 0x1) + pdimm->mirrored_dimm = 1; + break; + + default: + printf("unknown module_type 0x%02X\n", spd->module_type); + return 1; + } + + /* SDRAM device parameters */ + pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; + pdimm->n_col_addr = (spd->addressing & 0x7) + 9; + pdimm->n_banks_per_sdram_device = 8 << ((spd->density_banks >> 4) & 0x7); + + /* + * The SPD spec has not the ECC bit, + * We consider the DIMM as ECC capability + * when the extension bus exist + */ + if (pdimm->ec_sdram_width) + pdimm->edc_config = 0x02; + else + pdimm->edc_config = 0x00; + + /* + * The SPD spec has not the burst length byte + * but DDR3 spec has nature BL8 and BC4, + * BL8 -bit3, BC4 -bit2 + */ + pdimm->burst_lengths_bitmask = 0x0c; + pdimm->row_density = __ilog2(pdimm->rank_density); + + /* MTB - medium timebase + * The unit in the SPD spec is ns, + * We convert it to ps. + * eg: MTB = 0.125ns (125ps) + */ + mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor; + pdimm->mtb_ps = mtb_ps; + + /* + * FTB - fine timebase + * use 1/10th of ps as our unit to avoid floating point + * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps + */ + ftb_10th_ps = + ((spd->ftb_div & 0xf0) >> 4) * 10 / (spd->ftb_div & 0x0f); + pdimm->ftb_10th_ps = ftb_10th_ps; + /* + * sdram minimum cycle time + * we assume the MTB is 0.125ns + * eg: + * tck_min=15 MTB (1.875ns) ->DDR3-1066 + * =12 MTB (1.5ns) ->DDR3-1333 + * =10 MTB (1.25ns) ->DDR3-1600 + */ + pdimm->tckmin_x_ps = spd->tck_min * mtb_ps + + (spd->fine_tck_min * ftb_10th_ps) / 10; + + /* + * CAS latency supported + * bit4 - CL4 + * bit5 - CL5 + * bit18 - CL18 + */ + pdimm->caslat_x = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4; + + /* + * min CAS latency time + * eg: taa_min = + * DDR3-800D 100 MTB (12.5ns) + * DDR3-1066F 105 MTB (13.125ns) + * DDR3-1333H 108 MTB (13.5ns) + * DDR3-1600H 90 MTB (11.25ns) + */ + pdimm->taa_ps = spd->taa_min * mtb_ps + + (spd->fine_taa_min * ftb_10th_ps) / 10; + + /* + * min write recovery time + * eg: + * twr_min = 120 MTB (15ns) -> all speed grades. + */ + pdimm->twr_ps = spd->twr_min * mtb_ps; + + /* + * min RAS to CAS delay time + * eg: trcd_min = + * DDR3-800 100 MTB (12.5ns) + * DDR3-1066F 105 MTB (13.125ns) + * DDR3-1333H 108 MTB (13.5ns) + * DDR3-1600H 90 MTB (11.25) + */ + pdimm->trcd_ps = spd->trcd_min * mtb_ps + + (spd->fine_trcd_min * ftb_10th_ps) / 10; + + /* + * min row active to row active delay time + * eg: trrd_min = + * DDR3-800(1KB page) 80 MTB (10ns) + * DDR3-1333(1KB page) 48 MTB (6ns) + */ + pdimm->trrd_ps = spd->trrd_min * mtb_ps; + + /* + * min row precharge delay time + * eg: trp_min = + * DDR3-800D 100 MTB (12.5ns) + * DDR3-1066F 105 MTB (13.125ns) + * DDR3-1333H 108 MTB (13.5ns) + * DDR3-1600H 90 MTB (11.25ns) + */ + pdimm->trp_ps = spd->trp_min * mtb_ps + + (spd->fine_trp_min * ftb_10th_ps) / 10; + + /* min active to precharge delay time + * eg: tRAS_min = + * DDR3-800D 300 MTB (37.5ns) + * DDR3-1066F 300 MTB (37.5ns) + * DDR3-1333H 288 MTB (36ns) + * DDR3-1600H 280 MTB (35ns) + */ + pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) | spd->tras_min_lsb) + * mtb_ps; + /* + * min active to actice/refresh delay time + * eg: tRC_min = + * DDR3-800D 400 MTB (50ns) + * DDR3-1066F 405 MTB (50.625ns) + * DDR3-1333H 396 MTB (49.5ns) + * DDR3-1600H 370 MTB (46.25ns) + */ + pdimm->trc_ps = (((spd->tras_trc_ext & 0xf0) << 4) | spd->trc_min_lsb) + * mtb_ps + (spd->fine_trc_min * ftb_10th_ps) / 10; + /* + * min refresh recovery delay time + * eg: tRFC_min = + * 512Mb 720 MTB (90ns) + * 1Gb 880 MTB (110ns) + * 2Gb 1280 MTB (160ns) + */ + pdimm->trfc_ps = ((spd->trfc_min_msb << 8) | spd->trfc_min_lsb) + * mtb_ps; + /* + * min internal write to read command delay time + * eg: twtr_min = 40 MTB (7.5ns) - all speed bins. + * tWRT is at least 4 mclk independent of operating freq. + */ + pdimm->twtr_ps = spd->twtr_min * mtb_ps; + + /* + * min internal read to precharge command delay time + * eg: trtp_min = 40 MTB (7.5ns) - all speed bins. + * tRTP is at least 4 mclk independent of operating freq. + */ + pdimm->trtp_ps = spd->trtp_min * mtb_ps; + + /* + * Average periodic refresh interval + * tREFI = 7.8 us at normal temperature range + * = 3.9 us at ext temperature range + */ + pdimm->refresh_rate_ps = 7800000; + if ((spd->therm_ref_opt & 0x1) && !(spd->therm_ref_opt & 0x2)) { + pdimm->refresh_rate_ps = 3900000; + pdimm->extended_op_srt = 1; + } + + /* + * min four active window delay time + * eg: tfaw_min = + * DDR3-800(1KB page) 320 MTB (40ns) + * DDR3-1066(1KB page) 300 MTB (37.5ns) + * DDR3-1333(1KB page) 240 MTB (30ns) + * DDR3-1600(1KB page) 240 MTB (30ns) + */ + pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) + * mtb_ps; + + return 0; +} diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c new file mode 100644 index 0000000000..ebf3ed6f38 --- /dev/null +++ b/drivers/ddr/fsl/interactive.c @@ -0,0 +1,1871 @@ +/* + * Copyright 2010-2012 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. + * Based on code from spd_sdram.c + * Author: James Yang [at freescale.com] + * York Sun [at freescale.com] + */ + +#include +#include +#include +#include + +#include +#include + +/* Option parameter Structures */ +struct options_string { + const char *option_name; + size_t offset; + unsigned int size; + const char printhex; +}; + +static unsigned int picos_to_mhz(unsigned int picos) +{ + return 1000000 / picos; +} + +static void print_option_table(const struct options_string *table, + int table_size, + const void *base) +{ + unsigned int i; + unsigned int *ptr; + unsigned long long *ptr_l; + + for (i = 0; i < table_size; i++) { + switch (table[i].size) { + case 4: + ptr = (unsigned int *) (base + table[i].offset); + if (table[i].printhex) { + printf("%s = 0x%08X\n", + table[i].option_name, *ptr); + } else { + printf("%s = %u\n", + table[i].option_name, *ptr); + } + break; + case 8: + ptr_l = (unsigned long long *) (base + table[i].offset); + printf("%s = %llu\n", + table[i].option_name, *ptr_l); + break; + default: + printf("Unrecognized size!\n"); + break; + } + } +} + +static int handle_option_table(const struct options_string *table, + int table_size, + void *base, + const char *opt, + const char *val) +{ + unsigned int i; + unsigned int value, *ptr; + unsigned long long value_l, *ptr_l; + + for (i = 0; i < table_size; i++) { + if (strcmp(table[i].option_name, opt) != 0) + continue; + switch (table[i].size) { + case 4: + value = simple_strtoul(val, NULL, 0); + ptr = base + table[i].offset; + *ptr = value; + break; + case 8: + value_l = simple_strtoull(val, NULL, 0); + ptr_l = base + table[i].offset; + *ptr_l = value_l; + break; + default: + printf("Unrecognized size!\n"); + break; + } + return 1; + } + + return 0; +} + +static void fsl_ddr_generic_edit(void *pdata, + void *pend, + unsigned int element_size, + unsigned int element_num, + unsigned int value) +{ + char *pcdata = (char *)pdata; /* BIG ENDIAN ONLY */ + + pcdata += element_num * element_size; + if ((pcdata + element_size) > (char *) pend) { + printf("trying to write past end of data\n"); + return; + } + + switch (element_size) { + case 1: + __raw_writeb(value, pcdata); + break; + case 2: + __raw_writew(value, pcdata); + break; + case 4: + __raw_writel(value, pcdata); + break; + default: + printf("unexpected element size %u\n", element_size); + break; + } +} + +static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo, + unsigned int ctrl_num, + unsigned int dimm_num, + unsigned int element_num, + unsigned int value) +{ + generic_spd_eeprom_t *pspd; + + pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]); + fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value); +} + +#define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \ + sizeof((common_timing_params_t *)0)->x, 0} + +static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo, + unsigned int ctrl_num, + const char *optname_str, + const char *value_str) +{ + common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num]; + + static const struct options_string options[] = { + COMMON_TIMING(tckmin_x_ps), + COMMON_TIMING(tckmax_ps), + COMMON_TIMING(tckmax_max_ps), + COMMON_TIMING(trcd_ps), + COMMON_TIMING(trp_ps), + COMMON_TIMING(tras_ps), + COMMON_TIMING(twr_ps), + COMMON_TIMING(twtr_ps), + COMMON_TIMING(trfc_ps), + COMMON_TIMING(trrd_ps), + COMMON_TIMING(trc_ps), + COMMON_TIMING(refresh_rate_ps), + COMMON_TIMING(tis_ps), + COMMON_TIMING(tih_ps), + COMMON_TIMING(tds_ps), + COMMON_TIMING(tdh_ps), + COMMON_TIMING(trtp_ps), + COMMON_TIMING(tdqsq_max_ps), + COMMON_TIMING(tqhs_ps), + COMMON_TIMING(ndimms_present), + COMMON_TIMING(lowest_common_SPD_caslat), + COMMON_TIMING(highest_common_derated_caslat), + COMMON_TIMING(additive_latency), + COMMON_TIMING(all_dimms_burst_lengths_bitmask), + COMMON_TIMING(all_dimms_registered), + COMMON_TIMING(all_dimms_unbuffered), + COMMON_TIMING(all_dimms_ecc_capable), + COMMON_TIMING(total_mem), + COMMON_TIMING(base_address), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + if (handle_option_table(options, n_opts, p, optname_str, value_str)) + return; + + printf("Error: couldn't find option string %s\n", optname_str); +} + +#define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \ + sizeof((dimm_params_t *)0)->x, 0} + +static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, + unsigned int ctrl_num, + unsigned int dimm_num, + const char *optname_str, + const char *value_str) +{ + dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]); + + static const struct options_string options[] = { + DIMM_PARM(n_ranks), + DIMM_PARM(data_width), + DIMM_PARM(primary_sdram_width), + DIMM_PARM(ec_sdram_width), + DIMM_PARM(registered_dimm), + DIMM_PARM(device_width), + + DIMM_PARM(n_row_addr), + DIMM_PARM(n_col_addr), + DIMM_PARM(edc_config), + DIMM_PARM(n_banks_per_sdram_device), + DIMM_PARM(burst_lengths_bitmask), + DIMM_PARM(row_density), + + DIMM_PARM(tckmin_x_ps), + DIMM_PARM(tckmin_x_minus_1_ps), + DIMM_PARM(tckmin_x_minus_2_ps), + DIMM_PARM(tckmax_ps), + + DIMM_PARM(caslat_x), + DIMM_PARM(caslat_x_minus_1), + DIMM_PARM(caslat_x_minus_2), + + DIMM_PARM(caslat_lowest_derated), + + DIMM_PARM(trcd_ps), + DIMM_PARM(trp_ps), + DIMM_PARM(tras_ps), + DIMM_PARM(twr_ps), + DIMM_PARM(twtr_ps), + DIMM_PARM(trfc_ps), + DIMM_PARM(trrd_ps), + DIMM_PARM(trc_ps), + DIMM_PARM(refresh_rate_ps), + + DIMM_PARM(tis_ps), + DIMM_PARM(tih_ps), + DIMM_PARM(tds_ps), + DIMM_PARM(tdh_ps), + DIMM_PARM(trtp_ps), + DIMM_PARM(tdqsq_max_ps), + DIMM_PARM(tqhs_ps), + + DIMM_PARM(rank_density), + DIMM_PARM(capacity), + DIMM_PARM(base_address), + }; + + static const unsigned int n_opts = ARRAY_SIZE(options); + + if (handle_option_table(options, n_opts, p, optname_str, value_str)) + return; + + printf("couldn't find option string %s\n", optname_str); +} + +static void print_dimm_parameters(const dimm_params_t *pdimm) +{ + static const struct options_string options[] = { + DIMM_PARM(n_ranks), + DIMM_PARM(data_width), + DIMM_PARM(primary_sdram_width), + DIMM_PARM(ec_sdram_width), + DIMM_PARM(registered_dimm), + DIMM_PARM(device_width), + + DIMM_PARM(n_row_addr), + DIMM_PARM(n_col_addr), + DIMM_PARM(edc_config), + DIMM_PARM(n_banks_per_sdram_device), + + DIMM_PARM(tckmin_x_ps), + DIMM_PARM(tckmin_x_minus_1_ps), + DIMM_PARM(tckmin_x_minus_2_ps), + DIMM_PARM(tckmax_ps), + + DIMM_PARM(caslat_x), + DIMM_PARM(taa_ps), + DIMM_PARM(caslat_x_minus_1), + DIMM_PARM(caslat_x_minus_2), + DIMM_PARM(caslat_lowest_derated), + + DIMM_PARM(trcd_ps), + DIMM_PARM(trp_ps), + DIMM_PARM(tras_ps), + DIMM_PARM(twr_ps), + DIMM_PARM(twtr_ps), + DIMM_PARM(trfc_ps), + DIMM_PARM(trrd_ps), + DIMM_PARM(trc_ps), + DIMM_PARM(refresh_rate_ps), + + DIMM_PARM(tis_ps), + DIMM_PARM(tih_ps), + DIMM_PARM(tds_ps), + DIMM_PARM(tdh_ps), + DIMM_PARM(trtp_ps), + DIMM_PARM(tdqsq_max_ps), + DIMM_PARM(tqhs_ps), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + if (pdimm->n_ranks == 0) { + printf("DIMM not present\n"); + return; + } + printf("DIMM organization parameters:\n"); + printf("module part name = %s\n", pdimm->mpart); + printf("rank_density = %llu bytes (%llu megabytes)\n", + pdimm->rank_density, pdimm->rank_density / 0x100000); + printf("capacity = %llu bytes (%llu megabytes)\n", + pdimm->capacity, pdimm->capacity / 0x100000); + printf("burst_lengths_bitmask = %02X\n", + pdimm->burst_lengths_bitmask); + printf("base_addresss = %llu (%08llX %08llX)\n", + pdimm->base_address, + (pdimm->base_address >> 32), + pdimm->base_address & 0xFFFFFFFF); + print_option_table(options, n_opts, pdimm); +} + +static void print_lowest_common_dimm_parameters( + const common_timing_params_t *plcd_dimm_params) +{ + static const struct options_string options[] = { + COMMON_TIMING(tckmax_max_ps), + COMMON_TIMING(trcd_ps), + COMMON_TIMING(trp_ps), + COMMON_TIMING(tras_ps), + COMMON_TIMING(twr_ps), + COMMON_TIMING(twtr_ps), + COMMON_TIMING(trfc_ps), + COMMON_TIMING(trrd_ps), + COMMON_TIMING(trc_ps), + COMMON_TIMING(refresh_rate_ps), + COMMON_TIMING(tis_ps), + COMMON_TIMING(tds_ps), + COMMON_TIMING(tdh_ps), + COMMON_TIMING(trtp_ps), + COMMON_TIMING(tdqsq_max_ps), + COMMON_TIMING(tqhs_ps), + COMMON_TIMING(lowest_common_SPD_caslat), + COMMON_TIMING(highest_common_derated_caslat), + COMMON_TIMING(additive_latency), + COMMON_TIMING(ndimms_present), + COMMON_TIMING(all_dimms_registered), + COMMON_TIMING(all_dimms_unbuffered), + COMMON_TIMING(all_dimms_ecc_capable), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + /* Clock frequencies */ + printf("tckmin_x_ps = %u (%u MHz)\n", + plcd_dimm_params->tckmin_x_ps, + picos_to_mhz(plcd_dimm_params->tckmin_x_ps)); + printf("tckmax_ps = %u (%u MHz)\n", + plcd_dimm_params->tckmax_ps, + picos_to_mhz(plcd_dimm_params->tckmax_ps)); + printf("all_dimms_burst_lengths_bitmask = %02X\n", + plcd_dimm_params->all_dimms_burst_lengths_bitmask); + + print_option_table(options, n_opts, plcd_dimm_params); + + printf("total_mem = %llu (%llu megabytes)\n", + plcd_dimm_params->total_mem, + plcd_dimm_params->total_mem / 0x100000); + printf("base_address = %llu (%llu megabytes)\n", + plcd_dimm_params->base_address, + plcd_dimm_params->base_address / 0x100000); +} + +#define CTRL_OPTIONS(x) {#x, offsetof(memctl_options_t, x), \ + sizeof((memctl_options_t *)0)->x, 0} +#define CTRL_OPTIONS_CS(x, y) {"cs" #x "_" #y, \ + offsetof(memctl_options_t, cs_local_opts[x].y), \ + sizeof((memctl_options_t *)0)->cs_local_opts[x].y, 0} + +static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, + unsigned int ctl_num, + const char *optname_str, + const char *value_str) +{ + memctl_options_t *p = &(pinfo->memctl_opts[ctl_num]); + /* + * This array all on the stack and *computed* each time this + * function is rung. + */ + static const struct options_string options[] = { + CTRL_OPTIONS_CS(0, odt_rd_cfg), + CTRL_OPTIONS_CS(0, odt_wr_cfg), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CTRL_OPTIONS_CS(1, odt_rd_cfg), + CTRL_OPTIONS_CS(1, odt_wr_cfg), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(2, odt_rd_cfg), + CTRL_OPTIONS_CS(2, odt_wr_cfg), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(3, odt_rd_cfg), + CTRL_OPTIONS_CS(3, odt_wr_cfg), +#endif +#if defined(CONFIG_SYS_FSL_DDR3) + CTRL_OPTIONS_CS(0, odt_rtt_norm), + CTRL_OPTIONS_CS(0, odt_rtt_wr), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CTRL_OPTIONS_CS(1, odt_rtt_norm), + CTRL_OPTIONS_CS(1, odt_rtt_wr), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(2, odt_rtt_norm), + CTRL_OPTIONS_CS(2, odt_rtt_wr), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(3, odt_rtt_norm), + CTRL_OPTIONS_CS(3, odt_rtt_wr), +#endif +#endif + CTRL_OPTIONS(memctl_interleaving), + CTRL_OPTIONS(memctl_interleaving_mode), + CTRL_OPTIONS(ba_intlv_ctl), + CTRL_OPTIONS(ecc_mode), + CTRL_OPTIONS(ecc_init_using_memctl), + CTRL_OPTIONS(dqs_config), + CTRL_OPTIONS(self_refresh_in_sleep), + CTRL_OPTIONS(dynamic_power), + CTRL_OPTIONS(data_bus_width), + CTRL_OPTIONS(burst_length), + CTRL_OPTIONS(cas_latency_override), + CTRL_OPTIONS(cas_latency_override_value), + CTRL_OPTIONS(use_derated_caslat), + CTRL_OPTIONS(additive_latency_override), + CTRL_OPTIONS(additive_latency_override_value), + CTRL_OPTIONS(clk_adjust), + CTRL_OPTIONS(cpo_override), + CTRL_OPTIONS(write_data_delay), + CTRL_OPTIONS(half_strength_driver_enable), + + /* + * These can probably be changed to 2T_EN and 3T_EN + * (using a leading numerical character) without problem + */ + CTRL_OPTIONS(twot_en), + CTRL_OPTIONS(threet_en), + CTRL_OPTIONS(ap_en), + CTRL_OPTIONS(x4_en), + CTRL_OPTIONS(bstopre), + CTRL_OPTIONS(wrlvl_override), + CTRL_OPTIONS(wrlvl_sample), + CTRL_OPTIONS(wrlvl_start), + CTRL_OPTIONS(rcw_override), + CTRL_OPTIONS(rcw_1), + CTRL_OPTIONS(rcw_2), + CTRL_OPTIONS(ddr_cdr1), + CTRL_OPTIONS(ddr_cdr2), + CTRL_OPTIONS(tcke_clock_pulse_width_ps), + CTRL_OPTIONS(tfaw_window_four_activates_ps), + CTRL_OPTIONS(trwt_override), + CTRL_OPTIONS(trwt), + }; + + static const unsigned int n_opts = ARRAY_SIZE(options); + + if (handle_option_table(options, n_opts, p, + optname_str, value_str)) + return; + + printf("couldn't find option string %s\n", optname_str); +} + +#define CFG_REGS(x) {#x, offsetof(fsl_ddr_cfg_regs_t, x), \ + sizeof((fsl_ddr_cfg_regs_t *)0)->x, 1} +#define CFG_REGS_CS(x, y) {"cs" #x "_" #y, \ + offsetof(fsl_ddr_cfg_regs_t, cs[x].y), \ + sizeof((fsl_ddr_cfg_regs_t *)0)->cs[x].y, 1} + +static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) +{ + unsigned int i; + static const struct options_string options[] = { + CFG_REGS_CS(0, bnds), + CFG_REGS_CS(0, config), + CFG_REGS_CS(0, config_2), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CFG_REGS_CS(1, bnds), + CFG_REGS_CS(1, config), + CFG_REGS_CS(1, config_2), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CFG_REGS_CS(2, bnds), + CFG_REGS_CS(2, config), + CFG_REGS_CS(2, config_2), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CFG_REGS_CS(3, bnds), + CFG_REGS_CS(3, config), + CFG_REGS_CS(3, config_2), +#endif + CFG_REGS(timing_cfg_3), + CFG_REGS(timing_cfg_0), + CFG_REGS(timing_cfg_1), + CFG_REGS(timing_cfg_2), + CFG_REGS(ddr_sdram_cfg), + CFG_REGS(ddr_sdram_cfg_2), + CFG_REGS(ddr_sdram_mode), + CFG_REGS(ddr_sdram_mode_2), + CFG_REGS(ddr_sdram_mode_3), + CFG_REGS(ddr_sdram_mode_4), + CFG_REGS(ddr_sdram_mode_5), + CFG_REGS(ddr_sdram_mode_6), + CFG_REGS(ddr_sdram_mode_7), + CFG_REGS(ddr_sdram_mode_8), + CFG_REGS(ddr_sdram_interval), + CFG_REGS(ddr_data_init), + CFG_REGS(ddr_sdram_clk_cntl), + CFG_REGS(ddr_init_addr), + CFG_REGS(ddr_init_ext_addr), + CFG_REGS(timing_cfg_4), + CFG_REGS(timing_cfg_5), + CFG_REGS(ddr_zq_cntl), + CFG_REGS(ddr_wrlvl_cntl), + CFG_REGS(ddr_wrlvl_cntl_2), + CFG_REGS(ddr_wrlvl_cntl_3), + CFG_REGS(ddr_sr_cntr), + CFG_REGS(ddr_sdram_rcw_1), + CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_cdr1), + CFG_REGS(ddr_cdr2), + CFG_REGS(err_disable), + CFG_REGS(err_int_en), + CFG_REGS(ddr_eor), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + print_option_table(options, n_opts, ddr); + + for (i = 0; i < 32; i++) + printf("debug_%02d = 0x%08X\n", i+1, ddr->debug[i]); +} + +static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo, + unsigned int ctrl_num, + const char *regname, + const char *value_str) +{ + unsigned int i; + fsl_ddr_cfg_regs_t *ddr; + char buf[20]; + static const struct options_string options[] = { + CFG_REGS_CS(0, bnds), + CFG_REGS_CS(0, config), + CFG_REGS_CS(0, config_2), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CFG_REGS_CS(1, bnds), + CFG_REGS_CS(1, config), + CFG_REGS_CS(1, config_2), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CFG_REGS_CS(2, bnds), + CFG_REGS_CS(2, config), + CFG_REGS_CS(2, config_2), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) + CFG_REGS_CS(3, bnds), + CFG_REGS_CS(3, config), + CFG_REGS_CS(3, config_2), +#endif + CFG_REGS(timing_cfg_3), + CFG_REGS(timing_cfg_0), + CFG_REGS(timing_cfg_1), + CFG_REGS(timing_cfg_2), + CFG_REGS(ddr_sdram_cfg), + CFG_REGS(ddr_sdram_cfg_2), + CFG_REGS(ddr_sdram_mode), + CFG_REGS(ddr_sdram_mode_2), + CFG_REGS(ddr_sdram_mode_3), + CFG_REGS(ddr_sdram_mode_4), + CFG_REGS(ddr_sdram_mode_5), + CFG_REGS(ddr_sdram_mode_6), + CFG_REGS(ddr_sdram_mode_7), + CFG_REGS(ddr_sdram_mode_8), + CFG_REGS(ddr_sdram_interval), + CFG_REGS(ddr_data_init), + CFG_REGS(ddr_sdram_clk_cntl), + CFG_REGS(ddr_init_addr), + CFG_REGS(ddr_init_ext_addr), + CFG_REGS(timing_cfg_4), + CFG_REGS(timing_cfg_5), + CFG_REGS(ddr_zq_cntl), + CFG_REGS(ddr_wrlvl_cntl), + CFG_REGS(ddr_wrlvl_cntl_2), + CFG_REGS(ddr_wrlvl_cntl_3), + CFG_REGS(ddr_sr_cntr), + CFG_REGS(ddr_sdram_rcw_1), + CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_cdr1), + CFG_REGS(ddr_cdr2), + CFG_REGS(err_disable), + CFG_REGS(err_int_en), + CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_sdram_rcw_2), + CFG_REGS(ddr_eor), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + debug("fsl_ddr_regs_edit: ctrl_num = %u, " + "regname = %s, value = %s\n", + ctrl_num, regname, value_str); + if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS) + return; + + ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]); + + if (handle_option_table(options, n_opts, ddr, regname, value_str)) + return; + + for (i = 0; i < 32; i++) { + unsigned int value = simple_strtoul(value_str, NULL, 0); + sprintf(buf, "debug_%u", i + 1); + if (strcmp(buf, regname) == 0) { + ddr->debug[i] = value; + return; + } + } + printf("Error: couldn't find register string %s\n", regname); +} + +#define CTRL_OPTIONS_HEX(x) {#x, offsetof(memctl_options_t, x), \ + sizeof((memctl_options_t *)0)->x, 1} + +static void print_memctl_options(const memctl_options_t *popts) +{ + static const struct options_string options[] = { + CTRL_OPTIONS_CS(0, odt_rd_cfg), + CTRL_OPTIONS_CS(0, odt_wr_cfg), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CTRL_OPTIONS_CS(1, odt_rd_cfg), + CTRL_OPTIONS_CS(1, odt_wr_cfg), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(2, odt_rd_cfg), + CTRL_OPTIONS_CS(2, odt_wr_cfg), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) + CTRL_OPTIONS_CS(3, odt_rd_cfg), + CTRL_OPTIONS_CS(3, odt_wr_cfg), +#endif +#if defined(CONFIG_SYS_FSL_DDR3) + CTRL_OPTIONS_CS(0, odt_rtt_norm), + CTRL_OPTIONS_CS(0, odt_rtt_wr), +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + CTRL_OPTIONS_CS(1, odt_rtt_norm), + CTRL_OPTIONS_CS(1, odt_rtt_wr), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + CTRL_OPTIONS_CS(2, odt_rtt_norm), + CTRL_OPTIONS_CS(2, odt_rtt_wr), +#endif +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) + CTRL_OPTIONS_CS(3, odt_rtt_norm), + CTRL_OPTIONS_CS(3, odt_rtt_wr), +#endif +#endif + CTRL_OPTIONS(memctl_interleaving), + CTRL_OPTIONS(memctl_interleaving_mode), + CTRL_OPTIONS_HEX(ba_intlv_ctl), + CTRL_OPTIONS(ecc_mode), + CTRL_OPTIONS(ecc_init_using_memctl), + CTRL_OPTIONS(dqs_config), + CTRL_OPTIONS(self_refresh_in_sleep), + CTRL_OPTIONS(dynamic_power), + CTRL_OPTIONS(data_bus_width), + CTRL_OPTIONS(burst_length), + CTRL_OPTIONS(cas_latency_override), + CTRL_OPTIONS(cas_latency_override_value), + CTRL_OPTIONS(use_derated_caslat), + CTRL_OPTIONS(additive_latency_override), + CTRL_OPTIONS(additive_latency_override_value), + CTRL_OPTIONS(clk_adjust), + CTRL_OPTIONS(cpo_override), + CTRL_OPTIONS(write_data_delay), + CTRL_OPTIONS(half_strength_driver_enable), + /* + * These can probably be changed to 2T_EN and 3T_EN + * (using a leading numerical character) without problem + */ + CTRL_OPTIONS(twot_en), + CTRL_OPTIONS(threet_en), + CTRL_OPTIONS(registered_dimm_en), + CTRL_OPTIONS(ap_en), + CTRL_OPTIONS(x4_en), + CTRL_OPTIONS(bstopre), + CTRL_OPTIONS(wrlvl_override), + CTRL_OPTIONS(wrlvl_sample), + CTRL_OPTIONS(wrlvl_start), + CTRL_OPTIONS(rcw_override), + CTRL_OPTIONS(rcw_1), + CTRL_OPTIONS(rcw_2), + CTRL_OPTIONS_HEX(ddr_cdr1), + CTRL_OPTIONS_HEX(ddr_cdr2), + CTRL_OPTIONS(tcke_clock_pulse_width_ps), + CTRL_OPTIONS(tfaw_window_four_activates_ps), + CTRL_OPTIONS(trwt_override), + CTRL_OPTIONS(trwt), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + print_option_table(options, n_opts, popts); +} + +#ifdef CONFIG_SYS_FSL_DDR1 +void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd) +{ + unsigned int i; + + printf("%-3d : %02x %s\n", 0, spd->info_size, + " spd->info_size, * 0 # bytes written into serial memory *"); + printf("%-3d : %02x %s\n", 1, spd->chip_size, + " spd->chip_size, * 1 Total # bytes of SPD memory device *"); + printf("%-3d : %02x %s\n", 2, spd->mem_type, + " spd->mem_type, * 2 Fundamental memory type *"); + printf("%-3d : %02x %s\n", 3, spd->nrow_addr, + " spd->nrow_addr, * 3 # of Row Addresses on this assembly *"); + printf("%-3d : %02x %s\n", 4, spd->ncol_addr, + " spd->ncol_addr, * 4 # of Column Addrs on this assembly *"); + printf("%-3d : %02x %s\n", 5, spd->nrows, + " spd->nrows * 5 # of DIMM Banks *"); + printf("%-3d : %02x %s\n", 6, spd->dataw_lsb, + " spd->dataw_lsb, * 6 Data Width lsb of this assembly *"); + printf("%-3d : %02x %s\n", 7, spd->dataw_msb, + " spd->dataw_msb, * 7 Data Width msb of this assembly *"); + printf("%-3d : %02x %s\n", 8, spd->voltage, + " spd->voltage, * 8 Voltage intf std of this assembly *"); + printf("%-3d : %02x %s\n", 9, spd->clk_cycle, + " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *"); + printf("%-3d : %02x %s\n", 10, spd->clk_access, + " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *"); + printf("%-3d : %02x %s\n", 11, spd->config, + " spd->config, * 11 DIMM Configuration type *"); + printf("%-3d : %02x %s\n", 12, spd->refresh, + " spd->refresh, * 12 Refresh Rate/Type *"); + printf("%-3d : %02x %s\n", 13, spd->primw, + " spd->primw, * 13 Primary SDRAM Width *"); + printf("%-3d : %02x %s\n", 14, spd->ecw, + " spd->ecw, * 14 Error Checking SDRAM width *"); + printf("%-3d : %02x %s\n", 15, spd->min_delay, + " spd->min_delay, * 15 Back to Back Random Access *"); + printf("%-3d : %02x %s\n", 16, spd->burstl, + " spd->burstl, * 16 Burst Lengths Supported *"); + printf("%-3d : %02x %s\n", 17, spd->nbanks, + " spd->nbanks, * 17 # of Banks on Each SDRAM Device *"); + printf("%-3d : %02x %s\n", 18, spd->cas_lat, + " spd->cas_lat, * 18 CAS# Latencies Supported *"); + printf("%-3d : %02x %s\n", 19, spd->cs_lat, + " spd->cs_lat, * 19 Chip Select Latency *"); + printf("%-3d : %02x %s\n", 20, spd->write_lat, + " spd->write_lat, * 20 Write Latency/Recovery *"); + printf("%-3d : %02x %s\n", 21, spd->mod_attr, + " spd->mod_attr, * 21 SDRAM Module Attributes *"); + printf("%-3d : %02x %s\n", 22, spd->dev_attr, + " spd->dev_attr, * 22 SDRAM Device Attributes *"); + printf("%-3d : %02x %s\n", 23, spd->clk_cycle2, + " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *"); + printf("%-3d : %02x %s\n", 24, spd->clk_access2, + " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *"); + printf("%-3d : %02x %s\n", 25, spd->clk_cycle3, + " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *"); + printf("%-3d : %02x %s\n", 26, spd->clk_access3, + " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *"); + printf("%-3d : %02x %s\n", 27, spd->trp, + " spd->trp, * 27 Min Row Precharge Time (tRP)*"); + printf("%-3d : %02x %s\n", 28, spd->trrd, + " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *"); + printf("%-3d : %02x %s\n", 29, spd->trcd, + " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *"); + printf("%-3d : %02x %s\n", 30, spd->tras, + " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *"); + printf("%-3d : %02x %s\n", 31, spd->bank_dens, + " spd->bank_dens, * 31 Density of each bank on module *"); + printf("%-3d : %02x %s\n", 32, spd->ca_setup, + " spd->ca_setup, * 32 Cmd + Addr signal input setup time *"); + printf("%-3d : %02x %s\n", 33, spd->ca_hold, + " spd->ca_hold, * 33 Cmd and Addr signal input hold time *"); + printf("%-3d : %02x %s\n", 34, spd->data_setup, + " spd->data_setup, * 34 Data signal input setup time *"); + printf("%-3d : %02x %s\n", 35, spd->data_hold, + " spd->data_hold, * 35 Data signal input hold time *"); + printf("%-3d : %02x %s\n", 36, spd->res_36_40[0], + " spd->res_36_40[0], * 36 Reserved / tWR *"); + printf("%-3d : %02x %s\n", 37, spd->res_36_40[1], + " spd->res_36_40[1], * 37 Reserved / tWTR *"); + printf("%-3d : %02x %s\n", 38, spd->res_36_40[2], + " spd->res_36_40[2], * 38 Reserved / tRTP *"); + printf("%-3d : %02x %s\n", 39, spd->res_36_40[3], + " spd->res_36_40[3], * 39 Reserved / mem_probe *"); + printf("%-3d : %02x %s\n", 40, spd->res_36_40[4], + " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *"); + printf("%-3d : %02x %s\n", 41, spd->trc, + " spd->trc, * 41 Min Active to Auto refresh time tRC *"); + printf("%-3d : %02x %s\n", 42, spd->trfc, + " spd->trfc, * 42 Min Auto to Active period tRFC *"); + printf("%-3d : %02x %s\n", 43, spd->tckmax, + " spd->tckmax, * 43 Max device cycle time tCKmax *"); + printf("%-3d : %02x %s\n", 44, spd->tdqsq, + " spd->tdqsq, * 44 Max DQS to DQ skew *"); + printf("%-3d : %02x %s\n", 45, spd->tqhs, + " spd->tqhs, * 45 Max Read DataHold skew tQHS *"); + printf("%-3d : %02x %s\n", 46, spd->res_46, + " spd->res_46, * 46 Reserved/ PLL Relock time *"); + printf("%-3d : %02x %s\n", 47, spd->dimm_height, + " spd->dimm_height * 47 SDRAM DIMM Height *"); + + printf("%-3d-%3d: ", 48, 61); + + for (i = 0; i < 14; i++) + printf("%02x", spd->res_48_61[i]); + + printf(" * 48-61 IDD in SPD and Reserved space *\n"); + + printf("%-3d : %02x %s\n", 62, spd->spd_rev, + " spd->spd_rev, * 62 SPD Data Revision Code *"); + printf("%-3d : %02x %s\n", 63, spd->cksum, + " spd->cksum, * 63 Checksum for bytes 0-62 *"); + printf("%-3d-%3d: ", 64, 71); + + for (i = 0; i < 8; i++) + printf("%02x", spd->mid[i]); + + printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n"); + printf("%-3d : %02x %s\n", 72, spd->mloc, + " spd->mloc, * 72 Manufacturing Location *"); + + printf("%-3d-%3d: >>", 73, 90); + + for (i = 0; i < 18; i++) + printf("%c", spd->mpart[i]); + + printf("<<* 73 Manufacturer's Part Number *\n"); + + printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1], + "* 91 Revision Code *"); + printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1], + "* 93 Manufacturing Date *"); + printf("%-3d-%3d: ", 95, 98); + + for (i = 0; i < 4; i++) + printf("%02x", spd->sernum[i]); + + printf("* 95 Assembly Serial Number *\n"); + + printf("%-3d-%3d: ", 99, 127); + + for (i = 0; i < 27; i++) + printf("%02x", spd->mspec[i]); + + printf("* 99 Manufacturer Specific Data *\n"); +} +#endif + +#ifdef CONFIG_SYS_FSL_DDR2 +void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd) +{ + unsigned int i; + + printf("%-3d : %02x %s\n", 0, spd->info_size, + " spd->info_size, * 0 # bytes written into serial memory *"); + printf("%-3d : %02x %s\n", 1, spd->chip_size, + " spd->chip_size, * 1 Total # bytes of SPD memory device *"); + printf("%-3d : %02x %s\n", 2, spd->mem_type, + " spd->mem_type, * 2 Fundamental memory type *"); + printf("%-3d : %02x %s\n", 3, spd->nrow_addr, + " spd->nrow_addr, * 3 # of Row Addresses on this assembly *"); + printf("%-3d : %02x %s\n", 4, spd->ncol_addr, + " spd->ncol_addr, * 4 # of Column Addrs on this assembly *"); + printf("%-3d : %02x %s\n", 5, spd->mod_ranks, + " spd->mod_ranks * 5 # of Module Rows on this assembly *"); + printf("%-3d : %02x %s\n", 6, spd->dataw, + " spd->dataw, * 6 Data Width of this assembly *"); + printf("%-3d : %02x %s\n", 7, spd->res_7, + " spd->res_7, * 7 Reserved *"); + printf("%-3d : %02x %s\n", 8, spd->voltage, + " spd->voltage, * 8 Voltage intf std of this assembly *"); + printf("%-3d : %02x %s\n", 9, spd->clk_cycle, + " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *"); + printf("%-3d : %02x %s\n", 10, spd->clk_access, + " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *"); + printf("%-3d : %02x %s\n", 11, spd->config, + " spd->config, * 11 DIMM Configuration type *"); + printf("%-3d : %02x %s\n", 12, spd->refresh, + " spd->refresh, * 12 Refresh Rate/Type *"); + printf("%-3d : %02x %s\n", 13, spd->primw, + " spd->primw, * 13 Primary SDRAM Width *"); + printf("%-3d : %02x %s\n", 14, spd->ecw, + " spd->ecw, * 14 Error Checking SDRAM width *"); + printf("%-3d : %02x %s\n", 15, spd->res_15, + " spd->res_15, * 15 Reserved *"); + printf("%-3d : %02x %s\n", 16, spd->burstl, + " spd->burstl, * 16 Burst Lengths Supported *"); + printf("%-3d : %02x %s\n", 17, spd->nbanks, + " spd->nbanks, * 17 # of Banks on Each SDRAM Device *"); + printf("%-3d : %02x %s\n", 18, spd->cas_lat, + " spd->cas_lat, * 18 CAS# Latencies Supported *"); + printf("%-3d : %02x %s\n", 19, spd->mech_char, + " spd->mech_char, * 19 Mechanical Characteristics *"); + printf("%-3d : %02x %s\n", 20, spd->dimm_type, + " spd->dimm_type, * 20 DIMM type *"); + printf("%-3d : %02x %s\n", 21, spd->mod_attr, + " spd->mod_attr, * 21 SDRAM Module Attributes *"); + printf("%-3d : %02x %s\n", 22, spd->dev_attr, + " spd->dev_attr, * 22 SDRAM Device Attributes *"); + printf("%-3d : %02x %s\n", 23, spd->clk_cycle2, + " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *"); + printf("%-3d : %02x %s\n", 24, spd->clk_access2, + " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *"); + printf("%-3d : %02x %s\n", 25, spd->clk_cycle3, + " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *"); + printf("%-3d : %02x %s\n", 26, spd->clk_access3, + " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *"); + printf("%-3d : %02x %s\n", 27, spd->trp, + " spd->trp, * 27 Min Row Precharge Time (tRP)*"); + printf("%-3d : %02x %s\n", 28, spd->trrd, + " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *"); + printf("%-3d : %02x %s\n", 29, spd->trcd, + " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *"); + printf("%-3d : %02x %s\n", 30, spd->tras, + " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *"); + printf("%-3d : %02x %s\n", 31, spd->rank_dens, + " spd->rank_dens, * 31 Density of each rank on module *"); + printf("%-3d : %02x %s\n", 32, spd->ca_setup, + " spd->ca_setup, * 32 Cmd + Addr signal input setup time *"); + printf("%-3d : %02x %s\n", 33, spd->ca_hold, + " spd->ca_hold, * 33 Cmd and Addr signal input hold time *"); + printf("%-3d : %02x %s\n", 34, spd->data_setup, + " spd->data_setup, * 34 Data signal input setup time *"); + printf("%-3d : %02x %s\n", 35, spd->data_hold, + " spd->data_hold, * 35 Data signal input hold time *"); + printf("%-3d : %02x %s\n", 36, spd->twr, + " spd->twr, * 36 Write Recovery time tWR *"); + printf("%-3d : %02x %s\n", 37, spd->twtr, + " spd->twtr, * 37 Int write to read delay tWTR *"); + printf("%-3d : %02x %s\n", 38, spd->trtp, + " spd->trtp, * 38 Int read to precharge delay tRTP *"); + printf("%-3d : %02x %s\n", 39, spd->mem_probe, + " spd->mem_probe, * 39 Mem analysis probe characteristics *"); + printf("%-3d : %02x %s\n", 40, spd->trctrfc_ext, + " spd->trctrfc_ext, * 40 Extensions to trc and trfc *"); + printf("%-3d : %02x %s\n", 41, spd->trc, + " spd->trc, * 41 Min Active to Auto refresh time tRC *"); + printf("%-3d : %02x %s\n", 42, spd->trfc, + " spd->trfc, * 42 Min Auto to Active period tRFC *"); + printf("%-3d : %02x %s\n", 43, spd->tckmax, + " spd->tckmax, * 43 Max device cycle time tCKmax *"); + printf("%-3d : %02x %s\n", 44, spd->tdqsq, + " spd->tdqsq, * 44 Max DQS to DQ skew *"); + printf("%-3d : %02x %s\n", 45, spd->tqhs, + " spd->tqhs, * 45 Max Read DataHold skew tQHS *"); + printf("%-3d : %02x %s\n", 46, spd->pll_relock, + " spd->pll_relock, * 46 PLL Relock time *"); + printf("%-3d : %02x %s\n", 47, spd->t_casemax, + " spd->t_casemax, * 47 t_casemax *"); + printf("%-3d : %02x %s\n", 48, spd->psi_ta_dram, + " spd->psi_ta_dram, * 48 Thermal Resistance of DRAM Package " + "from Top (Case) to Ambient (Psi T-A DRAM) *"); + printf("%-3d : %02x %s\n", 49, spd->dt0_mode, + " spd->dt0_mode, * 49 DRAM Case Temperature Rise from " + "Ambient due to Activate-Precharge/Mode Bits " + "(DT0/Mode Bits) *)"); + printf("%-3d : %02x %s\n", 50, spd->dt2n_dt2q, + " spd->dt2n_dt2q, * 50 DRAM Case Temperature Rise from " + "Ambient due to Precharge/Quiet Standby " + "(DT2N/DT2Q) *"); + printf("%-3d : %02x %s\n", 51, spd->dt2p, + " spd->dt2p, * 51 DRAM Case Temperature Rise from " + "Ambient due to Precharge Power-Down (DT2P) *"); + printf("%-3d : %02x %s\n", 52, spd->dt3n, + " spd->dt3n, * 52 DRAM Case Temperature Rise from " + "Ambient due to Active Standby (DT3N) *"); + printf("%-3d : %02x %s\n", 53, spd->dt3pfast, + " spd->dt3pfast, * 53 DRAM Case Temperature Rise from " + "Ambient due to Active Power-Down with Fast PDN Exit " + "(DT3Pfast) *"); + printf("%-3d : %02x %s\n", 54, spd->dt3pslow, + " spd->dt3pslow, * 54 DRAM Case Temperature Rise from " + "Ambient due to Active Power-Down with Slow PDN Exit " + "(DT3Pslow) *"); + printf("%-3d : %02x %s\n", 55, spd->dt4r_dt4r4w, + " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from " + "Ambient due to Page Open Burst Read/DT4R4W Mode Bit " + "(DT4R/DT4R4W Mode Bit) *"); + printf("%-3d : %02x %s\n", 56, spd->dt5b, + " spd->dt5b, * 56 DRAM Case Temperature Rise from " + "Ambient due to Burst Refresh (DT5B) *"); + printf("%-3d : %02x %s\n", 57, spd->dt7, + " spd->dt7, * 57 DRAM Case Temperature Rise from " + "Ambient due to Bank Interleave Reads with " + "Auto-Precharge (DT7) *"); + printf("%-3d : %02x %s\n", 58, spd->psi_ta_pll, + " spd->psi_ta_pll, * 58 Thermal Resistance of PLL Package form" + " Top (Case) to Ambient (Psi T-A PLL) *"); + printf("%-3d : %02x %s\n", 59, spd->psi_ta_reg, + " spd->psi_ta_reg, * 59 Thermal Reisitance of Register Package" + " from Top (Case) to Ambient (Psi T-A Register) *"); + printf("%-3d : %02x %s\n", 60, spd->dtpllactive, + " spd->dtpllactive, * 60 PLL Case Temperature Rise from " + "Ambient due to PLL Active (DT PLL Active) *"); + printf("%-3d : %02x %s\n", 61, spd->dtregact, + " spd->dtregact, " + "* 61 Register Case Temperature Rise from Ambient due to " + "Register Active/Mode Bit (DT Register Active/Mode Bit) *"); + printf("%-3d : %02x %s\n", 62, spd->spd_rev, + " spd->spd_rev, * 62 SPD Data Revision Code *"); + printf("%-3d : %02x %s\n", 63, spd->cksum, + " spd->cksum, * 63 Checksum for bytes 0-62 *"); + + printf("%-3d-%3d: ", 64, 71); + + for (i = 0; i < 8; i++) + printf("%02x", spd->mid[i]); + + printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n"); + + printf("%-3d : %02x %s\n", 72, spd->mloc, + " spd->mloc, * 72 Manufacturing Location *"); + + printf("%-3d-%3d: >>", 73, 90); + for (i = 0; i < 18; i++) + printf("%c", spd->mpart[i]); + + + printf("<<* 73 Manufacturer's Part Number *\n"); + + printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1], + "* 91 Revision Code *"); + printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1], + "* 93 Manufacturing Date *"); + printf("%-3d-%3d: ", 95, 98); + + for (i = 0; i < 4; i++) + printf("%02x", spd->sernum[i]); + + printf("* 95 Assembly Serial Number *\n"); + + printf("%-3d-%3d: ", 99, 127); + for (i = 0; i < 27; i++) + printf("%02x", spd->mspec[i]); + + + printf("* 99 Manufacturer Specific Data *\n"); +} +#endif + +#ifdef CONFIG_SYS_FSL_DDR3 +void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd) +{ + unsigned int i; + + /* General Section: Bytes 0-59 */ + +#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, (u8)y); +#define PRINT_NNXXS(n0, n1, x0, x1, s) \ + printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1); + + PRINT_NXS(0, spd->info_size_crc, + "info_size_crc bytes written into serial memory, " + "CRC coverage"); + PRINT_NXS(1, spd->spd_rev, + "spd_rev SPD Revision"); + PRINT_NXS(2, spd->mem_type, + "mem_type Key Byte / DRAM Device Type"); + PRINT_NXS(3, spd->module_type, + "module_type Key Byte / Module Type"); + PRINT_NXS(4, spd->density_banks, + "density_banks SDRAM Density and Banks"); + PRINT_NXS(5, spd->addressing, + "addressing SDRAM Addressing"); + PRINT_NXS(6, spd->module_vdd, + "module_vdd Module Nominal Voltage, VDD"); + PRINT_NXS(7, spd->organization, + "organization Module Organization"); + PRINT_NXS(8, spd->bus_width, + "bus_width Module Memory Bus Width"); + PRINT_NXS(9, spd->ftb_div, + "ftb_div Fine Timebase (FTB) Dividend / Divisor"); + PRINT_NXS(10, spd->mtb_dividend, + "mtb_dividend Medium Timebase (MTB) Dividend"); + PRINT_NXS(11, spd->mtb_divisor, + "mtb_divisor Medium Timebase (MTB) Divisor"); + PRINT_NXS(12, spd->tck_min, + "tck_min SDRAM Minimum Cycle Time"); + PRINT_NXS(13, spd->res_13, + "res_13 Reserved"); + PRINT_NXS(14, spd->caslat_lsb, + "caslat_lsb CAS Latencies Supported, LSB"); + PRINT_NXS(15, spd->caslat_msb, + "caslat_msb CAS Latencies Supported, MSB"); + PRINT_NXS(16, spd->taa_min, + "taa_min Min CAS Latency Time"); + PRINT_NXS(17, spd->twr_min, + "twr_min Min Write REcovery Time"); + PRINT_NXS(18, spd->trcd_min, + "trcd_min Min RAS# to CAS# Delay Time"); + PRINT_NXS(19, spd->trrd_min, + "trrd_min Min Row Active to Row Active Delay Time"); + PRINT_NXS(20, spd->trp_min, + "trp_min Min Row Precharge Delay Time"); + PRINT_NXS(21, spd->tras_trc_ext, + "tras_trc_ext Upper Nibbles for tRAS and tRC"); + PRINT_NXS(22, spd->tras_min_lsb, + "tras_min_lsb Min Active to Precharge Delay Time, LSB"); + PRINT_NXS(23, spd->trc_min_lsb, + "trc_min_lsb Min Active to Active/Refresh Delay Time, LSB"); + PRINT_NXS(24, spd->trfc_min_lsb, + "trfc_min_lsb Min Refresh Recovery Delay Time LSB"); + PRINT_NXS(25, spd->trfc_min_msb, + "trfc_min_msb Min Refresh Recovery Delay Time MSB"); + PRINT_NXS(26, spd->twtr_min, + "twtr_min Min Internal Write to Read Command Delay Time"); + PRINT_NXS(27, spd->trtp_min, + "trtp_min " + "Min Internal Read to Precharge Command Delay Time"); + PRINT_NXS(28, spd->tfaw_msb, + "tfaw_msb Upper Nibble for tFAW"); + PRINT_NXS(29, spd->tfaw_min, + "tfaw_min Min Four Activate Window Delay Time"); + PRINT_NXS(30, spd->opt_features, + "opt_features SDRAM Optional Features"); + PRINT_NXS(31, spd->therm_ref_opt, + "therm_ref_opt SDRAM Thermal and Refresh Opts"); + PRINT_NXS(32, spd->therm_sensor, + "therm_sensor SDRAM Thermal Sensor"); + PRINT_NXS(33, spd->device_type, + "device_type SDRAM Device Type"); + PRINT_NXS(34, spd->fine_tck_min, + "fine_tck_min Fine offset for tCKmin"); + PRINT_NXS(35, spd->fine_taa_min, + "fine_taa_min Fine offset for tAAmin"); + PRINT_NXS(36, spd->fine_trcd_min, + "fine_trcd_min Fine offset for tRCDmin"); + PRINT_NXS(37, spd->fine_trp_min, + "fine_trp_min Fine offset for tRPmin"); + PRINT_NXS(38, spd->fine_trc_min, + "fine_trc_min Fine offset for tRCmin"); + + printf("%-3d-%3d: ", 39, 59); /* Reserved, General Section */ + + for (i = 39; i <= 59; i++) + printf("%02x ", spd->res_39_59[i - 39]); + + puts("\n"); + + switch (spd->module_type) { + case 0x02: /* UDIMM */ + case 0x03: /* SO-DIMM */ + case 0x04: /* Micro-DIMM */ + case 0x06: /* Mini-UDIMM */ + PRINT_NXS(60, spd->mod_section.unbuffered.mod_height, + "mod_height (Unbuffered) Module Nominal Height"); + PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness, + "mod_thickness (Unbuffered) Module Maximum Thickness"); + PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card, + "ref_raw_card (Unbuffered) Reference Raw Card Used"); + PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping, + "addr_mapping (Unbuffered) Address mapping from " + "Edge Connector to DRAM"); + break; + case 0x01: /* RDIMM */ + case 0x05: /* Mini-RDIMM */ + PRINT_NXS(60, spd->mod_section.registered.mod_height, + "mod_height (Registered) Module Nominal Height"); + PRINT_NXS(61, spd->mod_section.registered.mod_thickness, + "mod_thickness (Registered) Module Maximum Thickness"); + PRINT_NXS(62, spd->mod_section.registered.ref_raw_card, + "ref_raw_card (Registered) Reference Raw Card Used"); + PRINT_NXS(63, spd->mod_section.registered.modu_attr, + "modu_attr (Registered) DIMM Module Attributes"); + PRINT_NXS(64, spd->mod_section.registered.thermal, + "thermal (Registered) Thermal Heat " + "Spreader Solution"); + PRINT_NXS(65, spd->mod_section.registered.reg_id_lo, + "reg_id_lo (Registered) Register Manufacturer ID " + "Code, LSB"); + PRINT_NXS(66, spd->mod_section.registered.reg_id_hi, + "reg_id_hi (Registered) Register Manufacturer ID " + "Code, MSB"); + PRINT_NXS(67, spd->mod_section.registered.reg_rev, + "reg_rev (Registered) Register " + "Revision Number"); + PRINT_NXS(68, spd->mod_section.registered.reg_type, + "reg_type (Registered) Register Type"); + for (i = 69; i <= 76; i++) { + printf("%-3d : %02x rcw[%d]\n", i, + spd->mod_section.registered.rcw[i-69], i-69); + } + break; + default: + /* Module-specific Section, Unsupported Module Type */ + printf("%-3d-%3d: ", 60, 116); + + for (i = 60; i <= 116; i++) + printf("%02x", spd->mod_section.uc[i - 60]); + + break; + } + + /* Unique Module ID: Bytes 117-125 */ + PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106"); + PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106"); + PRINT_NXS(119, spd->mloc, "Mfg Location"); + PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date"); + + printf("%-3d-%3d: ", 122, 125); + + for (i = 122; i <= 125; i++) + printf("%02x ", spd->sernum[i - 122]); + printf(" Module Serial Number\n"); + + /* CRC: Bytes 126-127 */ + PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], " SPD CRC"); + + /* Other Manufacturer Fields and User Space: Bytes 128-255 */ + printf("%-3d-%3d: ", 128, 145); + for (i = 128; i <= 145; i++) + printf("%02x ", spd->mpart[i - 128]); + printf(" Mfg's Module Part Number\n"); + + PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1], + "Module Revision code"); + + PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106"); + PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106"); + + printf("%-3d-%3d: ", 150, 175); + for (i = 150; i <= 175; i++) + printf("%02x ", spd->msd[i - 150]); + printf(" Mfg's Specific Data\n"); + + printf("%-3d-%3d: ", 176, 255); + for (i = 176; i <= 255; i++) + printf("%02x", spd->cust[i - 176]); + printf(" Mfg's Specific Data\n"); + +} +#endif + +static inline void generic_spd_dump(const generic_spd_eeprom_t *spd) +{ +#if defined(CONFIG_SYS_FSL_DDR1) + ddr1_spd_dump(spd); +#elif defined(CONFIG_SYS_FSL_DDR2) + ddr2_spd_dump(spd); +#elif defined(CONFIG_SYS_FSL_DDR3) + ddr3_spd_dump(spd); +#endif +} + +static void fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo, + unsigned int ctrl_mask, + unsigned int dimm_mask, + unsigned int do_mask) +{ + unsigned int i, j, retval; + + /* STEP 1: DIMM SPD data */ + if (do_mask & STEP_GET_SPD) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + if (!(dimm_mask & (1 << j))) + continue; + + printf("SPD info: Controller=%u " + "DIMM=%u\n", i, j); + generic_spd_dump( + &(pinfo->spd_installed_dimms[i][j])); + printf("\n"); + } + printf("\n"); + } + printf("\n"); + } + + /* STEP 2: DIMM Parameters */ + if (do_mask & STEP_COMPUTE_DIMM_PARMS) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + if (!(dimm_mask & (1 << j))) + continue; + printf("DIMM parameters: Controller=%u " + "DIMM=%u\n", i, j); + print_dimm_parameters( + &(pinfo->dimm_params[i][j])); + printf("\n"); + } + printf("\n"); + } + printf("\n"); + } + + /* STEP 3: Common Parameters */ + if (do_mask & STEP_COMPUTE_COMMON_PARMS) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + printf("\"lowest common\" DIMM parameters: " + "Controller=%u\n", i); + print_lowest_common_dimm_parameters( + &pinfo->common_timing_params[i]); + printf("\n"); + } + printf("\n"); + } + + /* STEP 4: User Configuration Options */ + if (do_mask & STEP_GATHER_OPTS) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + printf("User Config Options: Controller=%u\n", i); + print_memctl_options(&pinfo->memctl_opts[i]); + printf("\n"); + } + printf("\n"); + } + + /* STEP 5: Address assignment */ + if (do_mask & STEP_ASSIGN_ADDRESSES) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + printf("Address Assignment: Controller=%u " + "DIMM=%u\n", i, j); + printf("Don't have this functionality yet\n"); + } + printf("\n"); + } + printf("\n"); + } + + /* STEP 6: computed controller register values */ + if (do_mask & STEP_COMPUTE_REGS) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (!(ctrl_mask & (1 << i))) + continue; + printf("Computed Register Values: Controller=%u\n", i); + print_fsl_memctl_config_regs( + &pinfo->fsl_ddr_config_reg[i]); + retval = check_fsl_memctl_config_regs( + &pinfo->fsl_ddr_config_reg[i]); + if (retval) { + printf("check_fsl_memctl_config_regs " + "result = %u\n", retval); + } + printf("\n"); + } + printf("\n"); + } +} + +struct data_strings { + const char *data_name; + unsigned int step_mask; + unsigned int dimm_number_required; +}; + +#define DATA_OPTIONS(name, step, dimm) {#name, step, dimm} + +static unsigned int fsl_ddr_parse_interactive_cmd( + char **argv, + int argc, + unsigned int *pstep_mask, + unsigned int *pctlr_mask, + unsigned int *pdimm_mask, + unsigned int *pdimm_number_required + ) { + + static const struct data_strings options[] = { + DATA_OPTIONS(spd, STEP_GET_SPD, 1), + DATA_OPTIONS(dimmparms, STEP_COMPUTE_DIMM_PARMS, 1), + DATA_OPTIONS(commonparms, STEP_COMPUTE_COMMON_PARMS, 0), + DATA_OPTIONS(opts, STEP_GATHER_OPTS, 0), + DATA_OPTIONS(addresses, STEP_ASSIGN_ADDRESSES, 0), + DATA_OPTIONS(regs, STEP_COMPUTE_REGS, 0), + }; + static const unsigned int n_opts = ARRAY_SIZE(options); + + unsigned int i, j; + unsigned int error = 0; + + for (i = 1; i < argc; i++) { + unsigned int matched = 0; + + for (j = 0; j < n_opts; j++) { + if (strcmp(options[j].data_name, argv[i]) != 0) + continue; + *pstep_mask |= options[j].step_mask; + *pdimm_number_required = + options[j].dimm_number_required; + matched = 1; + break; + } + + if (matched) + continue; + + if (argv[i][0] == 'c') { + char c = argv[i][1]; + if (isdigit(c)) + *pctlr_mask |= 1 << (c - '0'); + continue; + } + + if (argv[i][0] == 'd') { + char c = argv[i][1]; + if (isdigit(c)) + *pdimm_mask |= 1 << (c - '0'); + continue; + } + + printf("unknown arg %s\n", argv[i]); + *pstep_mask = 0; + error = 1; + break; + } + + return error; +} + +int fsl_ddr_interactive_env_var_exists(void) +{ + char buffer[CONFIG_SYS_CBSIZE]; + + if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0) + return 1; + + return 0; +} + +unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set) +{ + unsigned long long ddrsize; + const char *prompt = "FSL DDR>"; + char buffer[CONFIG_SYS_CBSIZE]; + char buffer2[CONFIG_SYS_CBSIZE]; + char *p = NULL; + char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ + int argc; + unsigned int next_step = STEP_GET_SPD; + const char *usage = { + "commands:\n" + "print print SPD and intermediate computed data\n" + "reset reboot machine\n" + "recompute reload SPD and options to default and recompute regs\n" + "edit modify spd, parameter, or option\n" + "compute recompute registers from current next_step to end\n" + "copy copy parameters\n" + "next_step shows current next_step\n" + "help this message\n" + "go program the memory controller and continue with u-boot\n" + }; + + if (var_is_set) { + if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) { + p = buffer2; + } else { + var_is_set = 0; + } + } + + /* + * The strategy for next_step is that it points to the next + * step in the computation process that needs to be done. + */ + while (1) { + if (var_is_set) { + char *pend = strchr(p, ';'); + if (pend) { + /* found command separator, copy sub-command */ + *pend = '\0'; + strcpy(buffer, p); + p = pend + 1; + } else { + /* separator not found, copy whole string */ + strcpy(buffer, p); + p = NULL; + var_is_set = 0; + } + } else { + /* + * No need to worry for buffer overflow here in + * this function; readline() maxes out at CFG_CBSIZE + */ + readline_into_buffer(prompt, buffer, 0); + } + argc = parse_line(buffer, argv); + if (argc == 0) + continue; + + + if (strcmp(argv[0], "help") == 0) { + puts(usage); + continue; + } + + if (strcmp(argv[0], "next_step") == 0) { + printf("next_step = 0x%02X (%s)\n", + next_step, + step_to_string(next_step)); + continue; + } + + if (strcmp(argv[0], "copy") == 0) { + unsigned int error = 0; + unsigned int step_mask = 0; + unsigned int src_ctlr_mask = 0; + unsigned int src_dimm_mask = 0; + unsigned int dimm_number_required = 0; + unsigned int src_ctlr_num = 0; + unsigned int src_dimm_num = 0; + unsigned int dst_ctlr_num = -1; + unsigned int dst_dimm_num = -1; + unsigned int i, num_dest_parms; + + if (argc == 1) { + printf("copy \n"); + continue; + } + + error = fsl_ddr_parse_interactive_cmd( + argv, argc, + &step_mask, + &src_ctlr_mask, + &src_dimm_mask, + &dimm_number_required + ); + + /* XXX: only dimm_number_required and step_mask will + be used by this function. Parse the controller and + DIMM number separately because it is easier. */ + + if (error) + continue; + + /* parse source destination controller / DIMM */ + + num_dest_parms = dimm_number_required ? 2 : 1; + + for (i = 0; i < argc; i++) { + if (argv[i][0] == 'c') { + char c = argv[i][1]; + if (isdigit(c)) { + src_ctlr_num = (c - '0'); + break; + } + } + } + + for (i = 0; i < argc; i++) { + if (argv[i][0] == 'd') { + char c = argv[i][1]; + if (isdigit(c)) { + src_dimm_num = (c - '0'); + break; + } + } + } + + /* parse destination controller / DIMM */ + + for (i = argc - 1; i >= argc - num_dest_parms; i--) { + if (argv[i][0] == 'c') { + char c = argv[i][1]; + if (isdigit(c)) { + dst_ctlr_num = (c - '0'); + break; + } + } + } + + for (i = argc - 1; i >= argc - num_dest_parms; i--) { + if (argv[i][0] == 'd') { + char c = argv[i][1]; + if (isdigit(c)) { + dst_dimm_num = (c - '0'); + break; + } + } + } + + /* TODO: validate inputs */ + + debug("src_ctlr_num = %u, src_dimm_num = %u, dst_ctlr_num = %u, dst_dimm_num = %u, step_mask = %x\n", + src_ctlr_num, src_dimm_num, dst_ctlr_num, dst_dimm_num, step_mask); + + + switch (step_mask) { + + case STEP_GET_SPD: + memcpy(&(pinfo->spd_installed_dimms[dst_ctlr_num][dst_dimm_num]), + &(pinfo->spd_installed_dimms[src_ctlr_num][src_dimm_num]), + sizeof(pinfo->spd_installed_dimms[0][0])); + break; + + case STEP_COMPUTE_DIMM_PARMS: + memcpy(&(pinfo->dimm_params[dst_ctlr_num][dst_dimm_num]), + &(pinfo->dimm_params[src_ctlr_num][src_dimm_num]), + sizeof(pinfo->dimm_params[0][0])); + break; + + case STEP_COMPUTE_COMMON_PARMS: + memcpy(&(pinfo->common_timing_params[dst_ctlr_num]), + &(pinfo->common_timing_params[src_ctlr_num]), + sizeof(pinfo->common_timing_params[0])); + break; + + case STEP_GATHER_OPTS: + memcpy(&(pinfo->memctl_opts[dst_ctlr_num]), + &(pinfo->memctl_opts[src_ctlr_num]), + sizeof(pinfo->memctl_opts[0])); + break; + + /* someday be able to have addresses to copy addresses... */ + + case STEP_COMPUTE_REGS: + memcpy(&(pinfo->fsl_ddr_config_reg[dst_ctlr_num]), + &(pinfo->fsl_ddr_config_reg[src_ctlr_num]), + sizeof(pinfo->memctl_opts[0])); + break; + + default: + printf("unexpected step_mask value\n"); + } + + continue; + + } + + if (strcmp(argv[0], "edit") == 0) { + unsigned int error = 0; + unsigned int step_mask = 0; + unsigned int ctlr_mask = 0; + unsigned int dimm_mask = 0; + char *p_element = NULL; + char *p_value = NULL; + unsigned int dimm_number_required = 0; + unsigned int ctrl_num; + unsigned int dimm_num; + + if (argc == 1) { + /* Only the element and value must be last */ + printf("edit " + " \n"); + printf("for spd, specify byte number for " + "element\n"); + continue; + } + + error = fsl_ddr_parse_interactive_cmd( + argv, argc - 2, + &step_mask, + &ctlr_mask, + &dimm_mask, + &dimm_number_required + ); + + if (error) + continue; + + + /* Check arguments */ + + /* ERROR: If no steps were found */ + if (step_mask == 0) { + printf("Error: No valid steps were specified " + "in argument.\n"); + continue; + } + + /* ERROR: If multiple steps were found */ + if (step_mask & (step_mask - 1)) { + printf("Error: Multiple steps specified in " + "argument.\n"); + continue; + } + + /* ERROR: Controller not specified */ + if (ctlr_mask == 0) { + printf("Error: controller number not " + "specified or no element and " + "value specified\n"); + continue; + } + + if (ctlr_mask & (ctlr_mask - 1)) { + printf("Error: multiple controllers " + "specified, %X\n", ctlr_mask); + continue; + } + + /* ERROR: DIMM number not specified */ + if (dimm_number_required && dimm_mask == 0) { + printf("Error: DIMM number number not " + "specified or no element and " + "value specified\n"); + continue; + } + + if (dimm_mask & (dimm_mask - 1)) { + printf("Error: multipled DIMMs specified\n"); + continue; + } + + p_element = argv[argc - 2]; + p_value = argv[argc - 1]; + + ctrl_num = __ilog2(ctlr_mask); + dimm_num = __ilog2(dimm_mask); + + switch (step_mask) { + case STEP_GET_SPD: + { + unsigned int element_num; + unsigned int value; + + element_num = simple_strtoul(p_element, + NULL, 0); + value = simple_strtoul(p_value, + NULL, 0); + fsl_ddr_spd_edit(pinfo, + ctrl_num, + dimm_num, + element_num, + value); + next_step = STEP_COMPUTE_DIMM_PARMS; + } + break; + + case STEP_COMPUTE_DIMM_PARMS: + fsl_ddr_dimm_parameters_edit( + pinfo, ctrl_num, dimm_num, + p_element, p_value); + next_step = STEP_COMPUTE_COMMON_PARMS; + break; + + case STEP_COMPUTE_COMMON_PARMS: + lowest_common_dimm_parameters_edit(pinfo, + ctrl_num, p_element, p_value); + next_step = STEP_GATHER_OPTS; + break; + + case STEP_GATHER_OPTS: + fsl_ddr_options_edit(pinfo, ctrl_num, + p_element, p_value); + next_step = STEP_ASSIGN_ADDRESSES; + break; + + case STEP_ASSIGN_ADDRESSES: + printf("editing of address assignment " + "not yet implemented\n"); + break; + + case STEP_COMPUTE_REGS: + { + fsl_ddr_regs_edit(pinfo, + ctrl_num, + p_element, + p_value); + next_step = STEP_PROGRAM_REGS; + } + break; + + default: + printf("programming error\n"); + while (1) + ; + break; + } + continue; + } + + if (strcmp(argv[0], "reset") == 0) { + /* + * Reboot machine. + * Args don't seem to matter because this + * doesn't return + */ + do_reset(NULL, 0, 0, NULL); + printf("Reset didn't work\n"); + } + + if (strcmp(argv[0], "recompute") == 0) { + /* + * Recalculate everything, starting with + * loading SPD EEPROM from DIMMs + */ + next_step = STEP_GET_SPD; + ddrsize = fsl_ddr_compute(pinfo, next_step, 0); + continue; + } + + if (strcmp(argv[0], "compute") == 0) { + /* + * Compute rest of steps starting at + * the current next_step/ + */ + ddrsize = fsl_ddr_compute(pinfo, next_step, 0); + continue; + } + + if (strcmp(argv[0], "print") == 0) { + unsigned int error = 0; + unsigned int step_mask = 0; + unsigned int ctlr_mask = 0; + unsigned int dimm_mask = 0; + unsigned int dimm_number_required = 0; + + if (argc == 1) { + printf("print [c] [d] [spd] [dimmparms] " + "[commonparms] [opts] [addresses] [regs]\n"); + continue; + } + + error = fsl_ddr_parse_interactive_cmd( + argv, argc, + &step_mask, + &ctlr_mask, + &dimm_mask, + &dimm_number_required + ); + + if (error) + continue; + + /* If no particular controller was found, print all */ + if (ctlr_mask == 0) + ctlr_mask = 0xFF; + + /* If no particular dimm was found, print all dimms. */ + if (dimm_mask == 0) + dimm_mask = 0xFF; + + /* If no steps were found, print all steps. */ + if (step_mask == 0) + step_mask = STEP_ALL; + + fsl_ddr_printinfo(pinfo, ctlr_mask, + dimm_mask, step_mask); + continue; + } + + if (strcmp(argv[0], "go") == 0) { + if (next_step) + ddrsize = fsl_ddr_compute(pinfo, next_step, 0); + break; + } + + printf("unknown command %s\n", argv[0]); + } + + debug("end of memory = %llu\n", (u64)ddrsize); + + return ddrsize; +} diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c new file mode 100644 index 0000000000..610318ad1e --- /dev/null +++ b/drivers/ddr/fsl/lc_common_dimm_params.c @@ -0,0 +1,526 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include + +#include + +#if defined(CONFIG_SYS_FSL_DDR3) +static unsigned int +compute_cas_latency_ddr3(const dimm_params_t *dimm_params, + common_timing_params_t *outpdimm, + unsigned int number_of_dimms) +{ + unsigned int i; + unsigned int taamin_ps = 0; + unsigned int tckmin_x_ps = 0; + unsigned int common_caslat; + unsigned int caslat_actual; + unsigned int retry = 16; + unsigned int tmp; + const unsigned int mclk_ps = get_memory_clk_period_ps(); + + /* compute the common CAS latency supported between slots */ + tmp = dimm_params[0].caslat_x; + for (i = 1; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) + tmp &= dimm_params[i].caslat_x; + } + common_caslat = tmp; + + /* compute the max tAAmin tCKmin between slots */ + for (i = 0; i < number_of_dimms; i++) { + taamin_ps = max(taamin_ps, dimm_params[i].taa_ps); + tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps); + } + /* validate if the memory clk is in the range of dimms */ + if (mclk_ps < tckmin_x_ps) { + printf("DDR clock (MCLK cycle %u ps) is faster than " + "the slowest DIMM(s) (tCKmin %u ps) can support.\n", + mclk_ps, tckmin_x_ps); + } + /* determine the acutal cas latency */ + caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps; + /* check if the dimms support the CAS latency */ + while (!(common_caslat & (1 << caslat_actual)) && retry > 0) { + caslat_actual++; + retry--; + } + /* once the caculation of caslat_actual is completed + * we must verify that this CAS latency value does not + * exceed tAAmax, which is 20 ns for all DDR3 speed grades + */ + if (caslat_actual * mclk_ps > 20000) { + printf("The choosen cas latency %d is too large\n", + caslat_actual); + } + outpdimm->lowest_common_SPD_caslat = caslat_actual; + + return 0; +} +#endif + +/* + * compute_lowest_common_dimm_parameters() + * + * Determine the worst-case DIMM timing parameters from the set of DIMMs + * whose parameters have been computed into the array pointed to + * by dimm_params. + */ +unsigned int +compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, + common_timing_params_t *outpdimm, + const unsigned int number_of_dimms) +{ + unsigned int i, j; + + unsigned int tckmin_x_ps = 0; + unsigned int tckmax_ps = 0xFFFFFFFF; + unsigned int tckmax_max_ps = 0; + unsigned int trcd_ps = 0; + unsigned int trp_ps = 0; + unsigned int tras_ps = 0; + unsigned int twr_ps = 0; + unsigned int twtr_ps = 0; + unsigned int trfc_ps = 0; + unsigned int trrd_ps = 0; + unsigned int trc_ps = 0; + unsigned int refresh_rate_ps = 0; + unsigned int extended_op_srt = 1; + unsigned int tis_ps = 0; + unsigned int tih_ps = 0; + unsigned int tds_ps = 0; + unsigned int tdh_ps = 0; + unsigned int trtp_ps = 0; + unsigned int tdqsq_max_ps = 0; + unsigned int tqhs_ps = 0; + + unsigned int temp1, temp2; + unsigned int additive_latency = 0; +#if !defined(CONFIG_SYS_FSL_DDR3) + const unsigned int mclk_ps = get_memory_clk_period_ps(); + unsigned int lowest_good_caslat; + unsigned int not_ok; + + debug("using mclk_ps = %u\n", mclk_ps); +#endif + + temp1 = 0; + for (i = 0; i < number_of_dimms; i++) { + /* + * If there are no ranks on this DIMM, + * it probably doesn't exist, so skip it. + */ + if (dimm_params[i].n_ranks == 0) { + temp1++; + continue; + } + if (dimm_params[i].n_ranks == 4 && i != 0) { + printf("Found Quad-rank DIMM in wrong bank, ignored." + " Software may not run as expected.\n"); + temp1++; + continue; + } + + /* + * check if quad-rank DIMM is plugged if + * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined + * Only the board with proper design is capable + */ +#ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + if (dimm_params[i].n_ranks == 4 && \ + CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) { + printf("Found Quad-rank DIMM, not able to support."); + temp1++; + continue; + } +#endif + /* + * Find minimum tckmax_ps to find fastest slow speed, + * i.e., this is the slowest the whole system can go. + */ + tckmax_ps = min(tckmax_ps, dimm_params[i].tckmax_ps); + + /* Either find maximum value to determine slowest + * speed, delay, time, period, etc */ + tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps); + tckmax_max_ps = max(tckmax_max_ps, dimm_params[i].tckmax_ps); + trcd_ps = max(trcd_ps, dimm_params[i].trcd_ps); + trp_ps = max(trp_ps, dimm_params[i].trp_ps); + tras_ps = max(tras_ps, dimm_params[i].tras_ps); + twr_ps = max(twr_ps, dimm_params[i].twr_ps); + twtr_ps = max(twtr_ps, dimm_params[i].twtr_ps); + trfc_ps = max(trfc_ps, dimm_params[i].trfc_ps); + trrd_ps = max(trrd_ps, dimm_params[i].trrd_ps); + trc_ps = max(trc_ps, dimm_params[i].trc_ps); + tis_ps = max(tis_ps, dimm_params[i].tis_ps); + tih_ps = max(tih_ps, dimm_params[i].tih_ps); + tds_ps = max(tds_ps, dimm_params[i].tds_ps); + tdh_ps = max(tdh_ps, dimm_params[i].tdh_ps); + trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps); + tqhs_ps = max(tqhs_ps, dimm_params[i].tqhs_ps); + refresh_rate_ps = max(refresh_rate_ps, + dimm_params[i].refresh_rate_ps); + /* extended_op_srt is either 0 or 1, 0 having priority */ + extended_op_srt = min(extended_op_srt, + dimm_params[i].extended_op_srt); + + /* + * Find maximum tdqsq_max_ps to find slowest. + * + * FIXME: is finding the slowest value the correct + * strategy for this parameter? + */ + tdqsq_max_ps = max(tdqsq_max_ps, dimm_params[i].tdqsq_max_ps); + } + + outpdimm->ndimms_present = number_of_dimms - temp1; + + if (temp1 == number_of_dimms) { + debug("no dimms this memory controller\n"); + return 0; + } + + outpdimm->tckmin_x_ps = tckmin_x_ps; + outpdimm->tckmax_ps = tckmax_ps; + outpdimm->tckmax_max_ps = tckmax_max_ps; + outpdimm->trcd_ps = trcd_ps; + outpdimm->trp_ps = trp_ps; + outpdimm->tras_ps = tras_ps; + outpdimm->twr_ps = twr_ps; + outpdimm->twtr_ps = twtr_ps; + outpdimm->trfc_ps = trfc_ps; + outpdimm->trrd_ps = trrd_ps; + outpdimm->trc_ps = trc_ps; + outpdimm->refresh_rate_ps = refresh_rate_ps; + outpdimm->extended_op_srt = extended_op_srt; + outpdimm->tis_ps = tis_ps; + outpdimm->tih_ps = tih_ps; + outpdimm->tds_ps = tds_ps; + outpdimm->tdh_ps = tdh_ps; + outpdimm->trtp_ps = trtp_ps; + outpdimm->tdqsq_max_ps = tdqsq_max_ps; + outpdimm->tqhs_ps = tqhs_ps; + + /* Determine common burst length for all DIMMs. */ + temp1 = 0xff; + for (i = 0; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) { + temp1 &= dimm_params[i].burst_lengths_bitmask; + } + } + outpdimm->all_dimms_burst_lengths_bitmask = temp1; + + /* Determine if all DIMMs registered buffered. */ + temp1 = temp2 = 0; + for (i = 0; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) { + if (dimm_params[i].registered_dimm) { + temp1 = 1; +#ifndef CONFIG_SPL_BUILD + printf("Detected RDIMM %s\n", + dimm_params[i].mpart); +#endif + } else { + temp2 = 1; +#ifndef CONFIG_SPL_BUILD + printf("Detected UDIMM %s\n", + dimm_params[i].mpart); +#endif + } + } + } + + outpdimm->all_dimms_registered = 0; + outpdimm->all_dimms_unbuffered = 0; + if (temp1 && !temp2) { + outpdimm->all_dimms_registered = 1; + } else if (!temp1 && temp2) { + outpdimm->all_dimms_unbuffered = 1; + } else { + printf("ERROR: Mix of registered buffered and unbuffered " + "DIMMs detected!\n"); + } + + temp1 = 0; + if (outpdimm->all_dimms_registered) + for (j = 0; j < 16; j++) { + outpdimm->rcw[j] = dimm_params[0].rcw[j]; + for (i = 1; i < number_of_dimms; i++) { + if (!dimm_params[i].n_ranks) + continue; + if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) { + temp1 = 1; + break; + } + } + } + + if (temp1 != 0) + printf("ERROR: Mix different RDIMM detected!\n"); + +#if defined(CONFIG_SYS_FSL_DDR3) + if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms)) + return 1; +#else + /* + * Compute a CAS latency suitable for all DIMMs + * + * Strategy for SPD-defined latencies: compute only + * CAS latency defined by all DIMMs. + */ + + /* + * Step 1: find CAS latency common to all DIMMs using bitwise + * operation. + */ + temp1 = 0xFF; + for (i = 0; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks) { + temp2 = 0; + temp2 |= 1 << dimm_params[i].caslat_x; + temp2 |= 1 << dimm_params[i].caslat_x_minus_1; + temp2 |= 1 << dimm_params[i].caslat_x_minus_2; + /* + * FIXME: If there was no entry for X-2 (X-1) in + * the SPD, then caslat_x_minus_2 + * (caslat_x_minus_1) contains either 255 or + * 0xFFFFFFFF because that's what the glorious + * __ilog2 function returns for an input of 0. + * On 32-bit PowerPC, left shift counts with bit + * 26 set (that the value of 255 or 0xFFFFFFFF + * will have), cause the destination register to + * be 0. That is why this works. + */ + temp1 &= temp2; + } + } + + /* + * Step 2: check each common CAS latency against tCK of each + * DIMM's SPD. + */ + lowest_good_caslat = 0; + temp2 = 0; + while (temp1) { + not_ok = 0; + temp2 = __ilog2(temp1); + debug("checking common caslat = %u\n", temp2); + + /* Check if this CAS latency will work on all DIMMs at tCK. */ + for (i = 0; i < number_of_dimms; i++) { + if (!dimm_params[i].n_ranks) { + continue; + } + if (dimm_params[i].caslat_x == temp2) { + if (mclk_ps >= dimm_params[i].tckmin_x_ps) { + debug("CL = %u ok on DIMM %u at tCK=%u" + " ps with its tCKmin_X_ps of %u\n", + temp2, i, mclk_ps, + dimm_params[i].tckmin_x_ps); + continue; + } else { + not_ok++; + } + } + + if (dimm_params[i].caslat_x_minus_1 == temp2) { + unsigned int tckmin_x_minus_1_ps + = dimm_params[i].tckmin_x_minus_1_ps; + if (mclk_ps >= tckmin_x_minus_1_ps) { + debug("CL = %u ok on DIMM %u at " + "tCK=%u ps with its " + "tckmin_x_minus_1_ps of %u\n", + temp2, i, mclk_ps, + tckmin_x_minus_1_ps); + continue; + } else { + not_ok++; + } + } + + if (dimm_params[i].caslat_x_minus_2 == temp2) { + unsigned int tckmin_x_minus_2_ps + = dimm_params[i].tckmin_x_minus_2_ps; + if (mclk_ps >= tckmin_x_minus_2_ps) { + debug("CL = %u ok on DIMM %u at " + "tCK=%u ps with its " + "tckmin_x_minus_2_ps of %u\n", + temp2, i, mclk_ps, + tckmin_x_minus_2_ps); + continue; + } else { + not_ok++; + } + } + } + + if (!not_ok) { + lowest_good_caslat = temp2; + } + + temp1 &= ~(1 << temp2); + } + + debug("lowest common SPD-defined CAS latency = %u\n", + lowest_good_caslat); + outpdimm->lowest_common_SPD_caslat = lowest_good_caslat; + + + /* + * Compute a common 'de-rated' CAS latency. + * + * The strategy here is to find the *highest* dereated cas latency + * with the assumption that all of the DIMMs will support a dereated + * CAS latency higher than or equal to their lowest dereated value. + */ + temp1 = 0; + for (i = 0; i < number_of_dimms; i++) { + temp1 = max(temp1, dimm_params[i].caslat_lowest_derated); + } + outpdimm->highest_common_derated_caslat = temp1; + debug("highest common dereated CAS latency = %u\n", temp1); +#endif /* #if defined(CONFIG_SYS_FSL_DDR3) */ + + /* Determine if all DIMMs ECC capable. */ + temp1 = 1; + for (i = 0; i < number_of_dimms; i++) { + if (dimm_params[i].n_ranks && + !(dimm_params[i].edc_config & EDC_ECC)) { + temp1 = 0; + break; + } + } + if (temp1) { + debug("all DIMMs ECC capable\n"); + } else { + debug("Warning: not all DIMMs ECC capable, cant enable ECC\n"); + } + outpdimm->all_dimms_ecc_capable = temp1; + +#ifndef CONFIG_SYS_FSL_DDR3 + /* FIXME: move to somewhere else to validate. */ + if (mclk_ps > tckmax_max_ps) { + printf("Warning: some of the installed DIMMs " + "can not operate this slowly.\n"); + return 1; + } +#endif + /* + * Compute additive latency. + * + * For DDR1, additive latency should be 0. + * + * For DDR2, with ODT enabled, use "a value" less than ACTTORW, + * which comes from Trcd, and also note that: + * add_lat + caslat must be >= 4 + * + * For DDR3, we use the AL=0 + * + * When to use additive latency for DDR2: + * + * I. Because you are using CL=3 and need to do ODT on writes and + * want functionality. + * 1. Are you going to use ODT? (Does your board not have + * additional termination circuitry for DQ, DQS, DQS_, + * DM, RDQS, RDQS_ for x4/x8 configs?) + * 2. If so, is your lowest supported CL going to be 3? + * 3. If so, then you must set AL=1 because + * + * WL >= 3 for ODT on writes + * RL = AL + CL + * WL = RL - 1 + * -> + * WL = AL + CL - 1 + * AL + CL - 1 >= 3 + * AL + CL >= 4 + * QED + * + * RL >= 3 for ODT on reads + * RL = AL + CL + * + * Since CL aren't usually less than 2, AL=0 is a minimum, + * so the WL-derived AL should be the -- FIXME? + * + * II. Because you are using auto-precharge globally and want to + * use additive latency (posted CAS) to get more bandwidth. + * 1. Are you going to use auto-precharge mode globally? + * + * Use addtivie latency and compute AL to be 1 cycle less than + * tRCD, i.e. the READ or WRITE command is in the cycle + * immediately following the ACTIVATE command.. + * + * III. Because you feel like it or want to do some sort of + * degraded-performance experiment. + * 1. Do you just want to use additive latency because you feel + * like it? + * + * Validation: AL is less than tRCD, and within the other + * read-to-precharge constraints. + */ + + additive_latency = 0; + +#if defined(CONFIG_SYS_FSL_DDR2) + if (lowest_good_caslat < 4) { + additive_latency = (picos_to_mclk(trcd_ps) > lowest_good_caslat) + ? picos_to_mclk(trcd_ps) - lowest_good_caslat : 0; + if (mclk_to_picos(additive_latency) > trcd_ps) { + additive_latency = picos_to_mclk(trcd_ps); + debug("setting additive_latency to %u because it was " + " greater than tRCD_ps\n", additive_latency); + } + } + +#elif defined(CONFIG_SYS_FSL_DDR3) + /* + * The system will not use the global auto-precharge mode. + * However, it uses the page mode, so we set AL=0 + */ + additive_latency = 0; +#endif + + /* + * Validate additive latency + * FIXME: move to somewhere else to validate + * + * AL <= tRCD(min) + */ + if (mclk_to_picos(additive_latency) > trcd_ps) { + printf("Error: invalid additive latency exceeds tRCD(min).\n"); + return 1; + } + + /* + * RL = CL + AL; RL >= 3 for ODT_RD_CFG to be enabled + * WL = RL - 1; WL >= 3 for ODT_WL_CFG to be enabled + * ADD_LAT (the register) must be set to a value less + * than ACTTORW if WL = 1, then AL must be set to 1 + * RD_TO_PRE (the register) must be set to a minimum + * tRTP + AL if AL is nonzero + */ + + /* + * Additive latency will be applied only if the memctl option to + * use it. + */ + outpdimm->additive_latency = additive_latency; + + debug("tCKmin_ps = %u\n", outpdimm->tckmin_x_ps); + debug("trcd_ps = %u\n", outpdimm->trcd_ps); + debug("trp_ps = %u\n", outpdimm->trp_ps); + debug("tras_ps = %u\n", outpdimm->tras_ps); + debug("twr_ps = %u\n", outpdimm->twr_ps); + debug("twtr_ps = %u\n", outpdimm->twtr_ps); + debug("trfc_ps = %u\n", outpdimm->trfc_ps); + debug("trrd_ps = %u\n", outpdimm->trrd_ps); + debug("trc_ps = %u\n", outpdimm->trc_ps); + + return 0; +} diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c new file mode 100644 index 0000000000..c1cdbdf955 --- /dev/null +++ b/drivers/ddr/fsl/main.c @@ -0,0 +1,718 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +/* + * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. + * Based on code from spd_sdram.c + * Author: James Yang [at freescale.com] + */ + +#include +#include +#include +#include + +#include + +void fsl_ddr_set_lawbar( + const common_timing_params_t *memctl_common_params, + unsigned int memctl_interleaved, + unsigned int ctrl_num); +void fsl_ddr_set_intl3r(const unsigned int granule_size); + +#if defined(SPD_EEPROM_ADDRESS) || \ + defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \ + defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4) +#if (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS, +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ + [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ + [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */ +}; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { + [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ + [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ + [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ + [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ + [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */ + [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */ +}; + +#endif + +static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) +{ + int ret; + + i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); + + ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, + sizeof(generic_spd_eeprom_t)); + + if (ret) { + if (i2c_address == +#ifdef SPD_EEPROM_ADDRESS + SPD_EEPROM_ADDRESS +#elif defined(SPD_EEPROM_ADDRESS1) + SPD_EEPROM_ADDRESS1 +#endif + ) { + printf("DDR: failed to read SPD from address %u\n", + i2c_address); + } else { + debug("DDR: failed to read SPD from address %u\n", + i2c_address); + } + memset(spd, 0, sizeof(generic_spd_eeprom_t)); + } +} + +__attribute__((weak, alias("__get_spd"))) +void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address); + +void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, + unsigned int ctrl_num) +{ + unsigned int i; + unsigned int i2c_address = 0; + + if (ctrl_num >= CONFIG_NUM_DDR_CONTROLLERS) { + printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); + return; + } + + for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { + i2c_address = spd_i2c_addr[ctrl_num][i]; + get_spd(&(ctrl_dimms_spd[i]), i2c_address); + } +} +#else +void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, + unsigned int ctrl_num) +{ +} +#endif /* SPD_EEPROM_ADDRESSx */ + +/* + * ASSUMPTIONS: + * - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller + * - Same memory data bus width on all controllers + * + * NOTES: + * + * The memory controller and associated documentation use confusing + * terminology when referring to the orgranization of DRAM. + * + * Here is a terminology translation table: + * + * memory controller/documention |industry |this code |signals + * -------------------------------|-----------|-----------|----------------- + * physical bank/bank |rank |rank |chip select (CS) + * logical bank/sub-bank |bank |bank |bank address (BA) + * page/row |row |page |row address + * ??? |column |column |column address + * + * The naming confusion is further exacerbated by the descriptions of the + * memory controller interleaving feature, where accesses are interleaved + * _BETWEEN_ two seperate memory controllers. This is configured only in + * CS0_CONFIG[INTLV_CTL] of each memory controller. + * + * memory controller documentation | number of chip selects + * | per memory controller supported + * --------------------------------|----------------------------------------- + * cache line interleaving | 1 (CS0 only) + * page interleaving | 1 (CS0 only) + * bank interleaving | 1 (CS0 only) + * superbank interleraving | depends on bank (chip select) + * | interleraving [rank interleaving] + * | mode used on every memory controller + * + * Even further confusing is the existence of the interleaving feature + * _WITHIN_ each memory controller. The feature is referred to in + * documentation as chip select interleaving or bank interleaving, + * although it is configured in the DDR_SDRAM_CFG field. + * + * Name of field | documentation name | this code + * -----------------------------|-----------------------|------------------ + * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving + * | interleaving + */ + +const char *step_string_tbl[] = { + "STEP_GET_SPD", + "STEP_COMPUTE_DIMM_PARMS", + "STEP_COMPUTE_COMMON_PARMS", + "STEP_GATHER_OPTS", + "STEP_ASSIGN_ADDRESSES", + "STEP_COMPUTE_REGS", + "STEP_PROGRAM_REGS", + "STEP_ALL" +}; + +const char * step_to_string(unsigned int step) { + + unsigned int s = __ilog2(step); + + if ((1 << s) != step) + return step_string_tbl[7]; + + return step_string_tbl[s]; +} + +static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, + unsigned int dbw_cap_adj[]) +{ + int i, j; + unsigned long long total_mem, current_mem_base, total_ctlr_mem; + unsigned long long rank_density, ctlr_density = 0; + + /* + * If a reduced data width is requested, but the SPD + * specifies a physically wider device, adjust the + * computed dimm capacities accordingly before + * assigning addresses. + */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + unsigned int found = 0; + + switch (pinfo->memctl_opts[i].data_bus_width) { + case 2: + /* 16-bit */ + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + unsigned int dw; + if (!pinfo->dimm_params[i][j].n_ranks) + continue; + dw = pinfo->dimm_params[i][j].primary_sdram_width; + if ((dw == 72 || dw == 64)) { + dbw_cap_adj[i] = 2; + break; + } else if ((dw == 40 || dw == 32)) { + dbw_cap_adj[i] = 1; + break; + } + } + break; + + case 1: + /* 32-bit */ + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + unsigned int dw; + dw = pinfo->dimm_params[i][j].data_width; + if (pinfo->dimm_params[i][j].n_ranks + && (dw == 72 || dw == 64)) { + /* + * FIXME: can't really do it + * like this because this just + * further reduces the memory + */ + found = 1; + break; + } + } + if (found) { + dbw_cap_adj[i] = 1; + } + break; + + case 0: + /* 64-bit */ + break; + + default: + printf("unexpected data bus width " + "specified controller %u\n", i); + return 1; + } + debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); + } + + current_mem_base = 0ull; + total_mem = 0; + if (pinfo->memctl_opts[0].memctl_interleaving) { + rank_density = pinfo->dimm_params[0][0].rank_density >> + dbw_cap_adj[0]; + switch (pinfo->memctl_opts[0].ba_intlv_ctl & + FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + ctlr_density = 4 * rank_density; + break; + case FSL_DDR_CS0_CS1: + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + ctlr_density = 2 * rank_density; + break; + case FSL_DDR_CS2_CS3: + default: + ctlr_density = rank_density; + break; + } + debug("rank density is 0x%llx, ctlr density is 0x%llx\n", + rank_density, ctlr_density); + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (pinfo->memctl_opts[i].memctl_interleaving) { + switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + total_ctlr_mem = 2 * ctlr_density; + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + total_ctlr_mem = 3 * ctlr_density; + break; + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + total_ctlr_mem = 4 * ctlr_density; + break; + default: + panic("Unknown interleaving mode"); + } + pinfo->common_timing_params[i].base_address = + current_mem_base; + pinfo->common_timing_params[i].total_mem = + total_ctlr_mem; + total_mem = current_mem_base + total_ctlr_mem; + debug("ctrl %d base 0x%llx\n", i, current_mem_base); + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); + } else { + /* when 3rd controller not interleaved */ + current_mem_base = total_mem; + total_ctlr_mem = 0; + pinfo->common_timing_params[i].base_address = + current_mem_base; + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + unsigned long long cap = + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; + pinfo->dimm_params[i][j].base_address = + current_mem_base; + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); + current_mem_base += cap; + total_ctlr_mem += cap; + } + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); + pinfo->common_timing_params[i].total_mem = + total_ctlr_mem; + total_mem += total_ctlr_mem; + } + } + } else { + /* + * Simple linear assignment if memory + * controllers are not interleaved. + */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + total_ctlr_mem = 0; + pinfo->common_timing_params[i].base_address = + current_mem_base; + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + /* Compute DIMM base addresses. */ + unsigned long long cap = + pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; + pinfo->dimm_params[i][j].base_address = + current_mem_base; + debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); + current_mem_base += cap; + total_ctlr_mem += cap; + } + debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); + pinfo->common_timing_params[i].total_mem = + total_ctlr_mem; + total_mem += total_ctlr_mem; + } + } + debug("Total mem by %s is 0x%llx\n", __func__, total_mem); + + return total_mem; +} + +/* Use weak function to allow board file to override the address assignment */ +__attribute__((weak, alias("__step_assign_addresses"))) +unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, + unsigned int dbw_cap_adj[]); + +unsigned long long +fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, + unsigned int size_only) +{ + unsigned int i, j; + unsigned long long total_mem = 0; + int assert_reset; + + fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; + common_timing_params_t *timing_params = pinfo->common_timing_params; + assert_reset = board_need_mem_reset(); + + /* data bus width capacity adjust shift amount */ + unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS]; + + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + dbw_capacity_adjust[i] = 0; + } + + debug("starting at step %u (%s)\n", + start_step, step_to_string(start_step)); + + switch (start_step) { + case STEP_GET_SPD: +#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) + /* STEP 1: Gather all DIMM SPD data */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); + } + + case STEP_COMPUTE_DIMM_PARMS: + /* STEP 2: Compute DIMM parameters from SPD data */ + + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + unsigned int retval; + generic_spd_eeprom_t *spd = + &(pinfo->spd_installed_dimms[i][j]); + dimm_params_t *pdimm = + &(pinfo->dimm_params[i][j]); + + retval = compute_dimm_parameters(spd, pdimm, i); +#ifdef CONFIG_SYS_DDR_RAW_TIMING + if (!i && !j && retval) { + printf("SPD error on controller %d! " + "Trying fallback to raw timing " + "calculation\n", i); + fsl_ddr_get_dimm_params(pdimm, i, j); + } +#else + if (retval == 2) { + printf("Error: compute_dimm_parameters" + " non-zero returned FATAL value " + "for memctl=%u dimm=%u\n", i, j); + return 0; + } +#endif + if (retval) { + debug("Warning: compute_dimm_parameters" + " non-zero return value for memctl=%u " + "dimm=%u\n", i, j); + } + } + } + +#elif defined(CONFIG_SYS_DDR_RAW_TIMING) + case STEP_COMPUTE_DIMM_PARMS: + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { + dimm_params_t *pdimm = + &(pinfo->dimm_params[i][j]); + fsl_ddr_get_dimm_params(pdimm, i, j); + } + } + debug("Filling dimm parameters from board specific file\n"); +#endif + case STEP_COMPUTE_COMMON_PARMS: + /* + * STEP 3: Compute a common set of timing parameters + * suitable for all of the DIMMs on each memory controller + */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + debug("Computing lowest common DIMM" + " parameters for memctl=%u\n", i); + compute_lowest_common_dimm_parameters( + pinfo->dimm_params[i], + &timing_params[i], + CONFIG_DIMM_SLOTS_PER_CTLR); + } + + case STEP_GATHER_OPTS: + /* STEP 4: Gather configuration requirements from user */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + debug("Reloading memory controller " + "configuration options for memctl=%u\n", i); + /* + * This "reloads" the memory controller options + * to defaults. If the user "edits" an option, + * next_step points to the step after this, + * which is currently STEP_ASSIGN_ADDRESSES. + */ + populate_memctl_options( + timing_params[i].all_dimms_registered, + &pinfo->memctl_opts[i], + pinfo->dimm_params[i], i); + /* + * For RDIMMs, JEDEC spec requires clocks to be stable + * before reset signal is deasserted. For the boards + * using fixed parameters, this function should be + * be called from board init file. + */ + if (timing_params[i].all_dimms_registered) + assert_reset = 1; + } + if (assert_reset) { + debug("Asserting mem reset\n"); + board_assert_mem_reset(); + } + + case STEP_ASSIGN_ADDRESSES: + /* STEP 5: Assign addresses to chip selects */ + check_interleaving_options(pinfo); + total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); + + case STEP_COMPUTE_REGS: + /* STEP 6: compute controller register values */ + debug("FSL Memory ctrl register computation\n"); + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (timing_params[i].ndimms_present == 0) { + memset(&ddr_reg[i], 0, + sizeof(fsl_ddr_cfg_regs_t)); + continue; + } + + compute_fsl_memctl_config_regs( + &pinfo->memctl_opts[i], + &ddr_reg[i], &timing_params[i], + pinfo->dimm_params[i], + dbw_capacity_adjust[i], + size_only); + } + + default: + break; + } + + { + /* + * Compute the amount of memory available just by + * looking for the highest valid CSn_BNDS value. + * This allows us to also experiment with using + * only CS0 when using dual-rank DIMMs. + */ + unsigned int max_end = 0; + + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) { + fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; + if (reg->cs[j].config & 0x80000000) { + unsigned int end; + /* + * 0xfffffff is a special value we put + * for unused bnds + */ + if (reg->cs[j].bnds == 0xffffffff) + continue; + end = reg->cs[j].bnds & 0xffff; + if (end > max_end) { + max_end = end; + } + } + } + } + + total_mem = 1 + (((unsigned long long)max_end << 24ULL) + | 0xFFFFFFULL); + } + + return total_mem; +} + +/* + * fsl_ddr_sdram() -- this is the main function to be called by + * initdram() in the board file. + * + * It returns amount of memory configured in bytes. + */ +phys_size_t fsl_ddr_sdram(void) +{ + unsigned int i; + unsigned int law_memctl = LAW_TRGT_IF_DDR_1; + unsigned long long total_memory; + fsl_ddr_info_t info; + int deassert_reset; + + /* Reset info structure. */ + memset(&info, 0, sizeof(fsl_ddr_info_t)); + + /* Compute it once normally. */ +#ifdef CONFIG_FSL_DDR_INTERACTIVE + if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */ + total_memory = fsl_ddr_interactive(&info, 0); + } else if (fsl_ddr_interactive_env_var_exists()) { + total_memory = fsl_ddr_interactive(&info, 1); + } else +#endif + total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); + + /* setup 3-way interleaving before enabling DDRC */ + if (info.memctl_opts[0].memctl_interleaving) { + switch (info.memctl_opts[0].memctl_interleaving_mode) { + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + fsl_ddr_set_intl3r( + info.memctl_opts[0].memctl_interleaving_mode); + break; + default: + break; + } + } + + /* + * Program configuration registers. + * JEDEC specs requires clocks to be stable before deasserting reset + * for RDIMMs. Clocks start after chip select is enabled and clock + * control register is set. During step 1, all controllers have their + * registers set but not enabled. Step 2 proceeds after deasserting + * reset through board FPGA or GPIO. + * For non-registered DIMMs, initialization can go through but it is + * also OK to follow the same flow. + */ + deassert_reset = board_need_mem_reset(); + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (info.common_timing_params[i].all_dimms_registered) + deassert_reset = 1; + } + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + debug("Programming controller %u\n", i); + if (info.common_timing_params[i].ndimms_present == 0) { + debug("No dimms present on controller %u; " + "skipping programming\n", i); + continue; + } + /* + * The following call with step = 1 returns before enabling + * the controller. It has to finish with step = 2 later. + */ + fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i, + deassert_reset ? 1 : 0); + } + if (deassert_reset) { + /* Use board FPGA or GPIO to deassert reset signal */ + debug("Deasserting mem reset\n"); + board_deassert_mem_reset(); + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + /* Call with step = 2 to continue initialization */ + fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), + i, 2); + } + } + + /* program LAWs */ + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (info.memctl_opts[i].memctl_interleaving) { + switch (info.memctl_opts[i].memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + if (i == 0) { + law_memctl = LAW_TRGT_IF_DDR_INTRLV; + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } else if (i == 2) { + law_memctl = LAW_TRGT_IF_DDR_INTLV_34; + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + law_memctl = LAW_TRGT_IF_DDR_INTLV_123; + if (i == 0) { + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } + break; + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; + if (i == 0) + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + /* place holder for future 4-way interleaving */ + break; + default: + break; + } + } else { + switch (i) { + case 0: + law_memctl = LAW_TRGT_IF_DDR_1; + break; + case 1: + law_memctl = LAW_TRGT_IF_DDR_2; + break; + case 2: + law_memctl = LAW_TRGT_IF_DDR_3; + break; + case 3: + law_memctl = LAW_TRGT_IF_DDR_4; + break; + default: + break; + } + fsl_ddr_set_lawbar(&info.common_timing_params[i], + law_memctl, i); + } + } + + debug("total_memory by %s = %llu\n", __func__, total_memory); + +#if !defined(CONFIG_PHYS_64BIT) + /* Check for 4G or more. Bad. */ + if (total_memory >= (1ull << 32)) { + puts("Detected "); + print_size(total_memory, " of memory\n"); + printf(" This U-Boot only supports < 4G of DDR\n"); + printf(" You could rebuild it with CONFIG_PHYS_64BIT\n"); + printf(" "); /* re-align to match init_func_ram print */ + total_memory = CONFIG_MAX_MEM_MAPPED; + } +#endif + + return total_memory; +} + +/* + * fsl_ddr_sdram_size() - This function only returns the size of the total + * memory without setting ddr control registers. + */ +phys_size_t +fsl_ddr_sdram_size(void) +{ + fsl_ddr_info_t info; + unsigned long long total_memory = 0; + + memset(&info, 0 , sizeof(fsl_ddr_info_t)); + + /* Compute it once normally. */ + total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); + + return total_memory; +} diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen1.c b/drivers/ddr/fsl/mpc85xx_ddr_gen1.c new file mode 100644 index 0000000000..ff7d979d6a --- /dev/null +++ b/drivers/ddr/fsl/mpc85xx_ddr_gen1.c @@ -0,0 +1,89 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include + +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL +#endif + +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step) +{ + unsigned int i; + volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + if (ctrl_num != 0) { + printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); + return; + } + + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (i == 0) { + out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs0_config, regs->cs[i].config); + + } else if (i == 1) { + out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs1_config, regs->cs[i].config); + + } else if (i == 2) { + out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs2_config, regs->cs[i].config); + + } else if (i == 3) { + out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs3_config, regs->cs[i].config); + } + } + + out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); +#if defined(CONFIG_MPC8555) || defined(CONFIG_MPC8541) + out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); +#endif + + /* + * 200 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + */ + udelay(200); + asm volatile("sync;isync"); + + out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); + + asm("sync;isync;msync"); + udelay(500); +} + +#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) +/* + * Initialize all of memory for ECC, then enable errors. + */ + +void +ddr_enable_ecc(unsigned int dram_size) +{ + volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); + + dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size); + + /* + * Enable errors for ECC. + */ + debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable); + ddr->err_disable = 0x00000000; + asm("sync;isync;msync"); + debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable); +} + +#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */ diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen2.c b/drivers/ddr/fsl/mpc85xx_ddr_gen2.c new file mode 100644 index 0000000000..c22dea5c24 --- /dev/null +++ b/drivers/ddr/fsl/mpc85xx_ddr_gen2.c @@ -0,0 +1,95 @@ +/* + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL +#endif + +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step) +{ + unsigned int i; + ccsr_ddr_t *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + +#if defined(CONFIG_SYS_FSL_ERRATUM_NMG_DDR120) && defined(CONFIG_MPC85xx) + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + uint svr; +#endif + + if (ctrl_num) { + printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); + return; + } + +#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_DDR120 + /* + * Set the DDR IO receiver to an acceptable bias point. + * Fixed in Rev 2.1. + */ + svr = get_svr(); + if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0)) { + if ((regs->ddr_sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) == + SDRAM_CFG_SDRAM_TYPE_DDR2) + out_be32(&gur->ddrioovcr, 0x90000000); + else + out_be32(&gur->ddrioovcr, 0xA8000000); + } +#endif + + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (i == 0) { + out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs0_config, regs->cs[i].config); + + } else if (i == 1) { + out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs1_config, regs->cs[i].config); + + } else if (i == 2) { + out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs2_config, regs->cs[i].config); + + } else if (i == 3) { + out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs3_config, regs->cs[i].config); + } + } + + out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); + out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); + out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); + out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); + out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); + out_be32(&ddr->sdram_data_init, regs->ddr_data_init); + out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); + out_be32(&ddr->init_addr, regs->ddr_init_addr); + out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); + + /* + * 200 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + */ + udelay(200); + asm volatile("sync;isync"); + + out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); + + /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ + while (in_be32(&ddr->sdram_cfg_2) & 0x10) { + udelay(10000); /* throttle polling rate */ + } +} diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c new file mode 100644 index 0000000000..7b4e8ec93d --- /dev/null +++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c @@ -0,0 +1,464 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL +#endif + + +/* + * regs has the to-be-set values for DDR controller registers + * ctrl_num is the DDR controller number + * step: 0 goes through the initialization in one pass + * 1 sets registers and returns before enabling controller + * 2 resumes from step 1 and continues to initialize + * Dividing the initialization to two steps to deassert DDR reset signal + * to comply with JEDEC specs for RDIMMs. + */ +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step) +{ + unsigned int i, bus_width; + volatile ccsr_ddr_t *ddr; + u32 temp_sdram_cfg; + u32 total_gb_size_per_controller; + int timeout; +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + int timeout_save; + volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR; + unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t; + int csn = -1; +#endif + + switch (ctrl_num) { + case 0: + ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + break; +#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) + case 1: + ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; + break; +#endif + default: + printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); + return; + } + + if (step == 2) + goto step2; + + if (regs->ddr_eor) + out_be32(&ddr->eor, regs->ddr_eor); +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + debug("Workaround for ERRATUM_DDR111_DDR134\n"); + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; + cs_ea = regs->cs[i].bnds & 0xfff; + if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) { + csn = i; + csn_bnds_backup = regs->cs[i].bnds; + csn_bnds_t = (unsigned int *) ®s->cs[i].bnds; + if (cs_ea > 0xeff) + *csn_bnds_t = regs->cs[i].bnds + 0x01000000; + else + *csn_bnds_t = regs->cs[i].bnds + 0x01000100; + debug("Found cs%d_bns (0x%08x) covering 0xff000000, " + "change it to 0x%x\n", + csn, csn_bnds_backup, regs->cs[i].bnds); + break; + } + } +#endif + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (i == 0) { + out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs0_config, regs->cs[i].config); + out_be32(&ddr->cs0_config_2, regs->cs[i].config_2); + + } else if (i == 1) { + out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs1_config, regs->cs[i].config); + out_be32(&ddr->cs1_config_2, regs->cs[i].config_2); + + } else if (i == 2) { + out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs2_config, regs->cs[i].config); + out_be32(&ddr->cs2_config_2, regs->cs[i].config_2); + + } else if (i == 3) { + out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs3_config, regs->cs[i].config); + out_be32(&ddr->cs3_config_2, regs->cs[i].config_2); + } + } + + out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); + out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); + out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); + out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); + out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3); + out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4); + out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5); + out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6); + out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7); + out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8); + out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); + out_be32(&ddr->sdram_data_init, regs->ddr_data_init); + out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); + out_be32(&ddr->init_addr, regs->ddr_init_addr); + out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); + + out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4); + out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5); + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); +#ifndef CONFIG_SYS_FSL_DDR_EMU + /* + * Skip these two registers if running on emulator + * because emulator doesn't have skew between bytes. + */ + + if (regs->ddr_wrlvl_cntl_2) + out_be32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2); + if (regs->ddr_wrlvl_cntl_3) + out_be32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3); +#endif + + out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); + out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); + out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); + out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1); + out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); + out_be32(&ddr->err_disable, regs->err_disable); + out_be32(&ddr->err_int_en, regs->err_int_en); + for (i = 0; i < 32; i++) { + if (regs->debug[i]) { + debug("Write to debug_%d as %08x\n", i+1, regs->debug[i]); + out_be32(&ddr->debug[i], regs->debug[i]); + } + } +#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934 + out_be32(&ddr->debug[28], 0x30003000); +#endif + +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474 + out_be32(&ddr->debug[12], 0x00000015); + out_be32(&ddr->debug[21], 0x24000000); +#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */ + + /* + * For RDIMMs, JEDEC spec requires clocks to be stable before reset is + * deasserted. Clocks start when any chip select is enabled and clock + * control register is set. Because all DDR components are connected to + * one reset signal, this needs to be done in two steps. Step 1 is to + * get the clocks started. Step 2 resumes after reset signal is + * deasserted. + */ + if (step == 1) { + udelay(200); + return; + } + +step2: + /* Set, but do not enable the memory */ + temp_sdram_cfg = regs->ddr_sdram_cfg; + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg); +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003 + debug("Workaround for ERRATUM_DDR_A003\n"); + if (regs->ddr_sdram_rcw_2 & 0x00f00000) { + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); + out_be32(&ddr->debug[2], 0x00000400); + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff); + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb); + out_be32(&ddr->mtcr, 0); + out_be32(&ddr->debug[12], 0x00000015); + out_be32(&ddr->debug[21], 0x24000000); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN); + + asm volatile("sync;isync"); + while (!(in_be32(&ddr->debug[1]) & 0x2)) + ; + + switch (regs->ddr_sdram_rcw_2 & 0x00f00000) { + case 0x00000000: + out_be32(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL_CS0_CS1 | + 0x04000000 | + MD_CNTL_WRCW | + MD_CNTL_MD_VALUE(0x02)); + break; + case 0x00100000: + out_be32(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL_CS0_CS1 | + 0x04000000 | + MD_CNTL_WRCW | + MD_CNTL_MD_VALUE(0x0a)); + break; + case 0x00200000: + out_be32(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL_CS0_CS1 | + 0x04000000 | + MD_CNTL_WRCW | + MD_CNTL_MD_VALUE(0x12)); + break; + case 0x00300000: + out_be32(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL_CS0_CS1 | + 0x04000000 | + MD_CNTL_WRCW | + MD_CNTL_MD_VALUE(0x1a)); + break; + default: + out_be32(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL_CS0_CS1 | + 0x04000000 | + MD_CNTL_WRCW | + MD_CNTL_MD_VALUE(0x02)); + printf("Unsupported RC10\n"); + break; + } + + while (in_be32(&ddr->sdram_md_cntl) & 0x80000000) + ; + udelay(6); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->debug[2], 0x0); + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + out_be32(&ddr->debug[12], 0x0); + out_be32(&ddr->debug[21], 0x0); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); + + } +#endif + /* + * For 8572 DDR1 erratum - DDR controller may enter illegal state + * when operatiing in 32-bit bus mode with 4-beat bursts, + * This erratum does not affect DDR3 mode, only for DDR2 mode. + */ +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115 + debug("Workaround for ERRATUM_DDR_115\n"); + if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2) + && in_be32(&ddr->sdram_cfg) & 0x80000) { + /* set DEBUG_1[31] */ + setbits_be32(&ddr->debug[0], 1); + } +#endif +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + debug("Workaround for ERRATUM_DDR111_DDR134\n"); + /* + * This is the combined workaround for DDR111 and DDR134 + * following the published errata for MPC8572 + */ + + /* 1. Set EEBACR[3] */ + setbits_be32(&ecm->eebacr, 0x10000000); + debug("Setting EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); + + /* 2. Set DINIT in SDRAM_CFG_2*/ + setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_D_INIT); + debug("Setting sdram_cfg_2[D_INIT] to 0x%08x\n", + in_be32(&ddr->sdram_cfg_2)); + + /* 3. Set DEBUG_3[21] */ + setbits_be32(&ddr->debug[2], 0x400); + debug("Setting DEBUG_3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); + +#endif /* part 1 of the workaound */ + + /* + * 500 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + * DDR2 need 200 us, and DDR3 need 500 us from spec, + * we choose the max, that is 500 us for all of case. + */ + udelay(500); + asm volatile("sync;isync"); + + /* Let the controller go */ + temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI; + out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); + asm volatile("sync;isync"); + + total_gb_size_per_controller = 0; + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (!(regs->cs[i].config & 0x80000000)) + continue; + total_gb_size_per_controller += 1 << ( + ((regs->cs[i].config >> 14) & 0x3) + 2 + + ((regs->cs[i].config >> 8) & 0x7) + 12 + + ((regs->cs[i].config >> 0) & 0x7) + 8 + + 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) - + 26); /* minus 26 (count of 64M) */ + } + if (fsl_ddr_get_intl3r() & 0x80000000) /* 3-way interleaving */ + total_gb_size_per_controller *= 3; + else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */ + total_gb_size_per_controller <<= 1; + /* + * total memory / bus width = transactions needed + * transactions needed / data rate = seconds + * to add plenty of buffer, double the time + * For example, 2GB on 666MT/s 64-bit bus takes about 402ms + * Let's wait for 800ms + */ + bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) + >> SDRAM_CFG_DBW_SHIFT); + timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 / + (get_ddr_freq(0) >> 20)) << 1; +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + timeout_save = timeout; +#endif + total_gb_size_per_controller >>= 4; /* shift down to gb size */ + debug("total %d GB\n", total_gb_size_per_controller); + debug("Need to wait up to %d * 10ms\n", timeout); + + /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ + while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) && + (timeout >= 0)) { + udelay(10000); /* throttle polling rate */ + timeout--; + } + + if (timeout <= 0) + printf("Waiting for D_INIT timeout. Memory may not work.\n"); + +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + /* continue this workaround */ + + /* 4. Clear DEBUG3[21] */ + clrbits_be32(&ddr->debug[2], 0x400); + debug("Clearing D3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); + + /* DDR134 workaround starts */ + /* A: Clear sdram_cfg_2[odt_cfg] */ + clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_ODT_CFG_MASK); + debug("Clearing SDRAM_CFG2[ODT_CFG] to 0x%08x\n", + in_be32(&ddr->sdram_cfg_2)); + + /* B: Set DEBUG1[15] */ + setbits_be32(&ddr->debug[0], 0x10000); + debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); + + /* C: Set timing_cfg_2[cpo] to 0b11111 */ + setbits_be32(&ddr->timing_cfg_2, TIMING_CFG_2_CPO_MASK); + debug("Setting TMING_CFG_2[CPO] to 0x%08x\n", + in_be32(&ddr->timing_cfg_2)); + + /* D: Set D6 to 0x9f9f9f9f */ + out_be32(&ddr->debug[5], 0x9f9f9f9f); + debug("Setting D6 to 0x%08x\n", in_be32(&ddr->debug[5])); + + /* E: Set D7 to 0x9f9f9f9f */ + out_be32(&ddr->debug[6], 0x9f9f9f9f); + debug("Setting D7 to 0x%08x\n", in_be32(&ddr->debug[6])); + + /* F: Set D2[20] */ + setbits_be32(&ddr->debug[1], 0x800); + debug("Setting D2[20] to 0x%08x\n", in_be32(&ddr->debug[1])); + + /* G: Poll on D2[20] until cleared */ + while (in_be32(&ddr->debug[1]) & 0x800) + udelay(10000); /* throttle polling rate */ + + /* H: Clear D1[15] */ + clrbits_be32(&ddr->debug[0], 0x10000); + debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); + + /* I: Set sdram_cfg_2[odt_cfg] */ + setbits_be32(&ddr->sdram_cfg_2, + regs->ddr_sdram_cfg_2 & SDRAM_CFG2_ODT_CFG_MASK); + debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); + + /* Continuing with the DDR111 workaround */ + /* 5. Set D2[21] */ + setbits_be32(&ddr->debug[1], 0x400); + debug("Setting D2[21] to 0x%08x\n", in_be32(&ddr->debug[1])); + + /* 6. Poll D2[21] until its cleared */ + while (in_be32(&ddr->debug[1]) & 0x400) + udelay(10000); /* throttle polling rate */ + + /* 7. Wait for state machine 2nd run, roughly 400ms/GB */ + debug("Wait for %d * 10ms\n", timeout_save); + udelay(timeout_save * 10000); + + /* 8. Set sdram_cfg_2[dinit] if options requires */ + setbits_be32(&ddr->sdram_cfg_2, + regs->ddr_sdram_cfg_2 & SDRAM_CFG2_D_INIT); + debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); + + /* 9. Poll until dinit is cleared */ + timeout = timeout_save; + debug("Need to wait up to %d * 10ms\n", timeout); + while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) && + (timeout >= 0)) { + udelay(10000); /* throttle polling rate */ + timeout--; + } + + if (timeout <= 0) + printf("Waiting for D_INIT timeout. Memory may not work.\n"); + + /* 10. Clear EEBACR[3] */ + clrbits_be32(&ecm->eebacr, 10000000); + debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); + + if (csn != -1) { + csn_bnds_t = (unsigned int *) ®s->cs[csn].bnds; + *csn_bnds_t = csn_bnds_backup; + debug("Change cs%d_bnds back to 0x%08x\n", + csn, regs->cs[csn].bnds); + setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */ + switch (csn) { + case 0: + out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds); + break; + case 1: + out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); + break; + case 2: + out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); + break; + case 3: + out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); + break; + } + clrbits_be32(&ddr->sdram_cfg, 0x2); + } +#endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */ +} diff --git a/drivers/ddr/fsl/mpc86xx_ddr.c b/drivers/ddr/fsl/mpc86xx_ddr.c new file mode 100644 index 0000000000..caffbaf019 --- /dev/null +++ b/drivers/ddr/fsl/mpc86xx_ddr.c @@ -0,0 +1,85 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include + +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL +#endif + +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step) +{ + unsigned int i; + volatile ccsr_ddr_t *ddr; + + switch (ctrl_num) { + case 0: + ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + break; + case 1: + ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; + break; + default: + printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); + return; + } + + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (i == 0) { + out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs0_config, regs->cs[i].config); + + } else if (i == 1) { + out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs1_config, regs->cs[i].config); + + } else if (i == 2) { + out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs2_config, regs->cs[i].config); + + } else if (i == 3) { + out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); + out_be32(&ddr->cs3_config, regs->cs[i].config); + } + } + + out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); + out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); + out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); + out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); + out_be32(&ddr->sdram_mode_cntl, regs->ddr_sdram_md_cntl); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); + out_be32(&ddr->sdram_data_init, regs->ddr_data_init); + out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); + out_be32(&ddr->init_addr, regs->ddr_init_addr); + out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); + + debug("before go\n"); + + /* + * 200 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + */ + udelay(200); + asm volatile("sync;isync"); + + out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); + + /* + * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done + */ + while (in_be32(&ddr->sdram_cfg_2) & 0x10) { + udelay(10000); /* throttle polling rate */ + } +} diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c new file mode 100644 index 0000000000..4aafcceaf5 --- /dev/null +++ b/drivers/ddr/fsl/options.c @@ -0,0 +1,1147 @@ +/* + * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include + +/* + * Use our own stack based buffer before relocation to allow accessing longer + * hwconfig strings that might be in the environment before we've relocated. + * This is pretty fragile on both the use of stack and if the buffer is big + * enough. However we will get a warning from getenv_f for the later. + */ + +/* Board-specific functions defined in each board's ddr.c */ +extern void fsl_ddr_board_options(memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num); + +struct dynamic_odt { + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; +}; + +#ifdef CONFIG_SYS_FSL_DDR3 +static const struct dynamic_odt single_Q[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS_AND_OTHER_DIMM, + DDR3_RTT_20_OHM, + DDR3_RTT_120_OHM + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, /* tied high */ + DDR3_RTT_OFF, + DDR3_RTT_120_OHM + }, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS_AND_OTHER_DIMM, + DDR3_RTT_20_OHM, + DDR3_RTT_120_OHM + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, /* tied high */ + DDR3_RTT_OFF, + DDR3_RTT_120_OHM + } +}; + +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR3_RTT_OFF, + DDR3_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR3_RTT_30_OHM, + DDR3_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR3_RTT_30_OHM, + DDR3_RTT_OFF + } +}; + +static const struct dynamic_odt dual_DS[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR3_RTT_30_OHM, + DDR3_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_ALL, + DDR3_RTT_20_OHM, + DDR3_RTT_120_OHM + }, + {0, 0, 0, 0} +}; +static const struct dynamic_odt dual_SD[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_ALL, + DDR3_RTT_20_OHM, + DDR3_RTT_120_OHM + }, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR3_RTT_20_OHM, + DDR3_RTT_OFF + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_ALL, + DDR3_RTT_30_OHM, + DDR3_RTT_120_OHM + }, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_ALL, + DDR3_RTT_30_OHM, + DDR3_RTT_120_OHM + }, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR3_RTT_OFF, + DDR3_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt dual_0D[4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_SAME_DIMM, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR3_RTT_OFF, + DDR3_RTT_OFF + } +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + +}; + +static const struct dynamic_odt dual_0S[4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_40_OHM, + DDR3_RTT_OFF + }, + {0, 0, 0, 0} + +}; + +static const struct dynamic_odt odt_unknown[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR3_RTT_120_OHM, + DDR3_RTT_OFF + } +}; +#else /* CONFIG_SYS_FSL_DDR3 */ +static const struct dynamic_odt single_Q[4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + } +}; + +static const struct dynamic_odt dual_DS[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt dual_SD[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_OTHER_DIMM, + FSL_DDR_ODT_OTHER_DIMM, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0} +}; + +static const struct dynamic_odt dual_0D[4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_ALL, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + } +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + +}; + +static const struct dynamic_odt dual_0S[4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR2_RTT_150_OHM, + DDR2_RTT_OFF + }, + {0, 0, 0, 0} + +}; + +static const struct dynamic_odt odt_unknown[4] = { + { /* cs0 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs1 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + }, + { /* cs2 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_CS, + DDR2_RTT_75_OHM, + DDR2_RTT_OFF + }, + { /* cs3 */ + FSL_DDR_ODT_NEVER, + FSL_DDR_ODT_NEVER, + DDR2_RTT_OFF, + DDR2_RTT_OFF + } +}; +#endif + +/* + * Automatically seleect bank interleaving mode based on DIMMs + * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null. + * This function only deal with one or two slots per controller. + */ +static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm) +{ +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) + if (pdimm[0].n_ranks == 4) + return FSL_DDR_CS0_CS1_CS2_CS3; + else if (pdimm[0].n_ranks == 2) + return FSL_DDR_CS0_CS1; +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + if (pdimm[0].n_ranks == 4) + return FSL_DDR_CS0_CS1_CS2_CS3; +#endif + if (pdimm[0].n_ranks == 2) { + if (pdimm[1].n_ranks == 2) + return FSL_DDR_CS0_CS1_CS2_CS3; + else + return FSL_DDR_CS0_CS1; + } +#endif + return 0; +} + +unsigned int populate_memctl_options(int all_dimms_registered, + memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num) +{ + unsigned int i; + char buffer[HWCONFIG_BUFFER_SIZE]; + char *buf = NULL; +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) + const struct dynamic_odt *pdodt = odt_unknown; +#endif + ulong ddr_freq; + + /* + * Extract hwconfig from environment since we have not properly setup + * the environment but need it for ddr config params + */ + if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) + buf = buffer; + +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) + /* Chip select options. */ + if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) { + switch (pdimm[0].n_ranks) { + case 1: + pdodt = single_S; + break; + case 2: + pdodt = single_D; + break; + case 4: + pdodt = single_Q; + break; + } + } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) { + switch (pdimm[0].n_ranks) { +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + case 4: + pdodt = single_Q; + if (pdimm[1].n_ranks) + printf("Error: Quad- and Dual-rank DIMMs " + "cannot be used together\n"); + break; +#endif + case 2: + switch (pdimm[1].n_ranks) { + case 2: + pdodt = dual_DD; + break; + case 1: + pdodt = dual_DS; + break; + case 0: + pdodt = dual_D0; + break; + } + break; + case 1: + switch (pdimm[1].n_ranks) { + case 2: + pdodt = dual_SD; + break; + case 1: + pdodt = dual_SS; + break; + case 0: + pdodt = dual_S0; + break; + } + break; + case 0: + switch (pdimm[1].n_ranks) { + case 2: + pdodt = dual_0D; + break; + case 1: + pdodt = dual_0S; + break; + } + break; + } + } +#endif + + /* Pick chip-select local options. */ + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2) + popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; + popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; + popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; + popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; +#else + popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER; + popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS; +#endif + popts->cs_local_opts[i].auto_precharge = 0; + } + + /* Pick interleaving mode. */ + + /* + * 0 = no interleaving + * 1 = interleaving between 2 controllers + */ + popts->memctl_interleaving = 0; + + /* + * 0 = cacheline + * 1 = page + * 2 = (logical) bank + * 3 = superbank (only if CS interleaving is enabled) + */ + popts->memctl_interleaving_mode = 0; + + /* + * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl + * 1: page: bit to the left of the column bits selects the memctl + * 2: bank: bit to the left of the bank bits selects the memctl + * 3: superbank: bit to the left of the chip select selects the memctl + * + * NOTE: ba_intlv (rank interleaving) is independent of memory + * controller interleaving; it is only within a memory controller. + * Must use superbank interleaving if rank interleaving is used and + * memory controller interleaving is enabled. + */ + + /* + * 0 = no + * 0x40 = CS0,CS1 + * 0x20 = CS2,CS3 + * 0x60 = CS0,CS1 + CS2,CS3 + * 0x04 = CS0,CS1,CS2,CS3 + */ + popts->ba_intlv_ctl = 0; + + /* Memory Organization Parameters */ + popts->registered_dimm_en = all_dimms_registered; + + /* Operational Mode Paramters */ + + /* Pick ECC modes */ + popts->ecc_mode = 0; /* 0 = disabled, 1 = enabled */ +#ifdef CONFIG_DDR_ECC + if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) { + if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf)) + popts->ecc_mode = 1; + } else + popts->ecc_mode = 1; +#endif + popts->ecc_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */ + + /* + * Choose DQS config + * 0 for DDR1 + * 1 for DDR2 + */ +#if defined(CONFIG_SYS_FSL_DDR1) + popts->dqs_config = 0; +#elif defined(CONFIG_SYS_FSL_DDR2) || defined(CONFIG_SYS_FSL_DDR3) + popts->dqs_config = 1; +#endif + + /* Choose self-refresh during sleep. */ + popts->self_refresh_in_sleep = 1; + + /* Choose dynamic power management mode. */ + popts->dynamic_power = 0; + + /* + * check first dimm for primary sdram width + * presuming all dimms are similar + * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit + */ +#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2) + if (pdimm[0].n_ranks != 0) { + if ((pdimm[0].data_width >= 64) && \ + (pdimm[0].data_width <= 72)) + popts->data_bus_width = 0; + else if ((pdimm[0].data_width >= 32) || \ + (pdimm[0].data_width <= 40)) + popts->data_bus_width = 1; + else { + panic("Error: data width %u is invalid!\n", + pdimm[0].data_width); + } + } +#else + if (pdimm[0].n_ranks != 0) { + if (pdimm[0].primary_sdram_width == 64) + popts->data_bus_width = 0; + else if (pdimm[0].primary_sdram_width == 32) + popts->data_bus_width = 1; + else if (pdimm[0].primary_sdram_width == 16) + popts->data_bus_width = 2; + else { + panic("Error: primary sdram width %u is invalid!\n", + pdimm[0].primary_sdram_width); + } + } +#endif + + popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0; + + /* Choose burst length. */ +#if defined(CONFIG_SYS_FSL_DDR3) +#if defined(CONFIG_E500MC) + popts->otf_burst_chop_en = 0; /* on-the-fly burst chop disable */ + popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */ +#else + if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) { + /* 32-bit or 16-bit bus */ + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + } else { + popts->otf_burst_chop_en = 1; /* on-the-fly burst chop */ + popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ + } +#endif +#else + popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */ +#endif + + /* Choose ddr controller address mirror mode */ +#if defined(CONFIG_SYS_FSL_DDR3) + popts->mirrored_dimm = pdimm[0].mirrored_dimm; +#endif + + /* Global Timing Parameters. */ + debug("mclk_ps = %u ps\n", get_memory_clk_period_ps()); + + /* Pick a caslat override. */ + popts->cas_latency_override = 0; + popts->cas_latency_override_value = 3; + if (popts->cas_latency_override) { + debug("using caslat override value = %u\n", + popts->cas_latency_override_value); + } + + /* Decide whether to use the computed derated latency */ + popts->use_derated_caslat = 0; + + /* Choose an additive latency. */ + popts->additive_latency_override = 0; + popts->additive_latency_override_value = 3; + if (popts->additive_latency_override) { + debug("using additive latency override value = %u\n", + popts->additive_latency_override_value); + } + + /* + * 2T_EN setting + * + * Factors to consider for 2T_EN: + * - number of DIMMs installed + * - number of components, number of active ranks + * - how much time you want to spend playing around + */ + popts->twot_en = 0; + popts->threet_en = 0; + + /* for RDIMM, address parity enable */ + popts->ap_en = 1; + + /* + * BSTTOPRE precharge interval + * + * Set this to 0 for global auto precharge + * + * FIXME: Should this be configured in picoseconds? + * Why it should be in ps: better understanding of this + * relative to actual DRAM timing parameters such as tRAS. + * e.g. tRAS(min) = 40 ns + */ + popts->bstopre = 0x100; + + /* Minimum CKE pulse width -- tCKE(MIN) */ + popts->tcke_clock_pulse_width_ps + = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR); + + /* + * Window for four activates -- tFAW + * + * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only + * FIXME: varies depending upon number of column addresses or data + * FIXME: width, was considering looking at pdimm->primary_sdram_width + */ +#if defined(CONFIG_SYS_FSL_DDR1) + popts->tfaw_window_four_activates_ps = mclk_to_picos(1); + +#elif defined(CONFIG_SYS_FSL_DDR2) + /* + * x4/x8; some datasheets have 35000 + * x16 wide columns only? Use 50000? + */ + popts->tfaw_window_four_activates_ps = 37500; + +#elif defined(CONFIG_SYS_FSL_DDR3) + popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps; +#endif + popts->zq_en = 0; + popts->wrlvl_en = 0; +#if defined(CONFIG_SYS_FSL_DDR3) + /* + * due to ddr3 dimm is fly-by topology + * we suggest to enable write leveling to + * meet the tQDSS under different loading. + */ + popts->wrlvl_en = 1; + popts->zq_en = 1; + popts->wrlvl_override = 0; +#endif + + /* + * Check interleaving configuration from environment. + * Please refer to doc/README.fsl-ddr for the detail. + * + * If memory controller interleaving is enabled, then the data + * bus widths must be programmed identically for all memory controllers. + * + * XXX: Attempt to set all controllers to the same chip select + * interleaving mode. It will do a best effort to get the + * requested ranks interleaved together such that the result + * should be a subset of the requested configuration. + */ +#if (CONFIG_NUM_DDR_CONTROLLERS > 1) + if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) + goto done; + + if (pdimm[0].n_ranks == 0) { + printf("There is no rank on CS0 for controller %d.\n", ctrl_num); + popts->memctl_interleaving = 0; + goto done; + } + popts->memctl_interleaving = 1; + /* + * test null first. if CONFIG_HWCONFIG is not defined + * hwconfig_arg_cmp returns non-zero + */ + if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", + "null", buf)) { + popts->memctl_interleaving = 0; + debug("memory controller interleaving disabled.\n"); + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "cacheline", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_CACHE_LINE_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "page", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_PAGE_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "bank", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_BANK_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "superbank", buf)) { + popts->memctl_interleaving_mode = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : FSL_DDR_SUPERBANK_INTERLEAVING; + popts->memctl_interleaving = + ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ? + 0 : 1; +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_1KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_1KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_4KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_4KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "3way_8KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_3WAY_8KB_INTERLEAVING; +#elif (CONFIG_NUM_DDR_CONTROLLERS == 4) + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_1KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_1KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_4KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_4KB_INTERLEAVING; + } else if (hwconfig_subarg_cmp_f("fsl_ddr", + "ctlr_intlv", + "4way_8KB", buf)) { + popts->memctl_interleaving_mode = + FSL_DDR_4WAY_8KB_INTERLEAVING; +#endif + } else { + popts->memctl_interleaving = 0; + printf("hwconfig has unrecognized parameter for ctlr_intlv.\n"); + } +done: +#endif + if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) && + (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) { + /* test null first. if CONFIG_HWCONFIG is not defined, + * hwconfig_subarg_cmp_f returns non-zero */ + if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "null", buf)) + debug("bank interleaving disabled.\n"); + else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "cs0_cs1", buf)) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "cs2_cs3", buf)) + popts->ba_intlv_ctl = FSL_DDR_CS2_CS3; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "cs0_cs1_and_cs2_cs3", buf)) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "cs0_cs1_cs2_cs3", buf)) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", + "auto", buf)) + popts->ba_intlv_ctl = auto_bank_intlv(pdimm); + else + printf("hwconfig has unrecognized parameter for bank_intlv.\n"); + switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) + if (pdimm[0].n_ranks < 4) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(chip-select) for " + "CS0+CS1+CS2+CS3 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + if (pdimm[0].n_ranks == 4) + break; +#endif + if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(chip-select) for " + "CS0+CS1+CS2+CS3 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } + if (pdimm[0].capacity != pdimm[1].capacity) { + popts->ba_intlv_ctl = 0; + printf("Not identical DIMM size for " + "CS0+CS1+CS2+CS3 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } +#endif + break; + case FSL_DDR_CS0_CS1: + if (pdimm[0].n_ranks < 2) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(chip-select) for " + "CS0+CS1 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } + break; + case FSL_DDR_CS2_CS3: +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) + if (pdimm[0].n_ranks < 4) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(chip-select) for CS2+CS3 " + "on controller %d, interleaving disabled!\n", ctrl_num); + } +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) + if (pdimm[1].n_ranks < 2) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(chip-select) for CS2+CS3 " + "on controller %d, interleaving disabled!\n", ctrl_num); + } +#endif + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) + if (pdimm[0].n_ranks < 4) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(CS) for CS0+CS1 and " + "CS2+CS3 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) + if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(CS) for CS0+CS1 and " + "CS2+CS3 on controller %d, " + "interleaving disabled!\n", ctrl_num); + } +#endif + break; + default: + popts->ba_intlv_ctl = 0; + break; + } + } + + if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) { + if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf)) + popts->addr_hash = 0; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", + "true", buf)) + popts->addr_hash = 1; + } + + if (pdimm[0].n_ranks == 4) + popts->quad_rank_present = 1; + + ddr_freq = get_ddr_freq(0) / 1000000; + if (popts->registered_dimm_en) { + popts->rcw_override = 1; + popts->rcw_1 = 0x000a5a00; + if (ddr_freq <= 800) + popts->rcw_2 = 0x00000000; + else if (ddr_freq <= 1066) + popts->rcw_2 = 0x00100000; + else if (ddr_freq <= 1333) + popts->rcw_2 = 0x00200000; + else + popts->rcw_2 = 0x00300000; + } + + fsl_ddr_board_options(popts, pdimm, ctrl_num); + + return 0; +} + +void check_interleaving_options(fsl_ddr_info_t *pinfo) +{ + int i, j, k, check_n_ranks, intlv_invalid = 0; + unsigned int check_intlv, check_n_row_addr, check_n_col_addr; + unsigned long long check_rank_density; + struct dimm_params_s *dimm; + /* + * Check if all controllers are configured for memory + * controller interleaving. Identical dimms are recommended. At least + * the size, row and col address should be checked. + */ + j = 0; + check_n_ranks = pinfo->dimm_params[0][0].n_ranks; + check_rank_density = pinfo->dimm_params[0][0].rank_density; + check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; + check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; + check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + dimm = &pinfo->dimm_params[i][0]; + if (!pinfo->memctl_opts[i].memctl_interleaving) { + continue; + } else if (((check_rank_density != dimm->rank_density) || + (check_n_ranks != dimm->n_ranks) || + (check_n_row_addr != dimm->n_row_addr) || + (check_n_col_addr != dimm->n_col_addr) || + (check_intlv != + pinfo->memctl_opts[i].memctl_interleaving_mode))){ + intlv_invalid = 1; + break; + } else { + j++; + } + + } + if (intlv_invalid) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) + pinfo->memctl_opts[i].memctl_interleaving = 0; + printf("Not all DIMMs are identical. " + "Memory controller interleaving disabled.\n"); + } else { + switch (check_intlv) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + case FSL_DDR_PAGE_INTERLEAVING: + case FSL_DDR_BANK_INTERLEAVING: + case FSL_DDR_SUPERBANK_INTERLEAVING: + if (3 == CONFIG_NUM_DDR_CONTROLLERS) + k = 2; + else + k = CONFIG_NUM_DDR_CONTROLLERS; + break; + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + case FSL_DDR_4WAY_1KB_INTERLEAVING: + case FSL_DDR_4WAY_4KB_INTERLEAVING: + case FSL_DDR_4WAY_8KB_INTERLEAVING: + default: + k = CONFIG_NUM_DDR_CONTROLLERS; + break; + } + debug("%d of %d controllers are interleaving.\n", j, k); + if (j && (j != k)) { + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) + pinfo->memctl_opts[i].memctl_interleaving = 0; + printf("Not all controllers have compatible " + "interleaving mode. All disabled.\n"); + } + } + debug("Checking interleaving options completed\n"); +} + +int fsl_use_spd(void) +{ + int use_spd = 0; + +#ifdef CONFIG_DDR_SPD + char buffer[HWCONFIG_BUFFER_SIZE]; + char *buf = NULL; + + /* + * Extract hwconfig from environment since we have not properly setup + * the environment but need it for ddr config params + */ + if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) + buf = buffer; + + /* if hwconfig is not enabled, or "sdram" is not defined, use spd */ + if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) { + if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf)) + use_spd = 1; + else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", + "fixed", buf)) + use_spd = 0; + else + use_spd = 1; + } else + use_spd = 1; +#endif + + return use_spd; +} diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c new file mode 100644 index 0000000000..45a7bcc080 --- /dev/null +++ b/drivers/ddr/fsl/util.c @@ -0,0 +1,265 @@ +/* + * Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include + +/* To avoid 64-bit full-divides, we factor this here */ +#define ULL_2E12 2000000000000ULL +#define UL_5POW12 244140625UL +#define UL_2POW13 (1UL << 13) + +#define ULL_8FS 0xFFFFFFFFULL + +/* + * Round up mclk_ps to nearest 1 ps in memory controller code + * if the error is 0.5ps or more. + * + * If an imprecise data rate is too high due to rounding error + * propagation, compute a suitably rounded mclk_ps to compute + * a working memory controller configuration. + */ +unsigned int get_memory_clk_period_ps(void) +{ + unsigned int data_rate = get_ddr_freq(0); + unsigned int result; + + /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ + unsigned long long rem, mclk_ps = ULL_2E12; + + /* Now perform the big divide, the result fits in 32-bits */ + rem = do_div(mclk_ps, data_rate); + result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; + + return result; +} + +/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */ +unsigned int picos_to_mclk(unsigned int picos) +{ + unsigned long long clks, clks_rem; + unsigned long data_rate = get_ddr_freq(0); + + /* Short circuit for zero picos */ + if (!picos) + return 0; + + /* First multiply the time by the data rate (32x32 => 64) */ + clks = picos * (unsigned long long)data_rate; + /* + * Now divide by 5^12 and track the 32-bit remainder, then divide + * by 2*(2^12) using shifts (and updating the remainder). + */ + clks_rem = do_div(clks, UL_5POW12); + clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12; + clks >>= 13; + + /* If we had a remainder greater than the 1ps error, then round up */ + if (clks_rem > data_rate) + clks++; + + /* Clamp to the maximum representable value */ + if (clks > ULL_8FS) + clks = ULL_8FS; + return (unsigned int) clks; +} + +unsigned int mclk_to_picos(unsigned int mclk) +{ + return get_memory_clk_period_ps() * mclk; +} + +void +__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, + unsigned int law_memctl, + unsigned int ctrl_num) +{ + unsigned long long base = memctl_common_params->base_address; + unsigned long long size = memctl_common_params->total_mem; + + /* + * If no DIMMs on this controller, do not proceed any further. + */ + if (!memctl_common_params->ndimms_present) { + return; + } + +#if !defined(CONFIG_PHYS_64BIT) + if (base >= CONFIG_MAX_MEM_MAPPED) + return; + if ((base + size) >= CONFIG_MAX_MEM_MAPPED) + size = CONFIG_MAX_MEM_MAPPED - base; +#endif + if (set_ddr_laws(base, size, law_memctl) < 0) { + printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num, + law_memctl); + return ; + } + debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n", + base, size, law_memctl); +} + +__attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void +fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, + unsigned int memctl_interleaved, + unsigned int ctrl_num); + +void fsl_ddr_set_intl3r(const unsigned int granule_size) +{ +#ifdef CONFIG_E6500 + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); + *mcintl3r = 0x80000000 | (granule_size & 0x1f); + debug("Enable MCINTL3R with granule size 0x%x\n", granule_size); +#endif +} + +u32 fsl_ddr_get_intl3r(void) +{ + u32 val = 0; +#ifdef CONFIG_E6500 + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); + val = *mcintl3r; +#endif + return val; +} + +void board_add_ram_info(int use_default) +{ + ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_FSL_DDR_ADDR); + +#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3) + u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); +#endif +#if (CONFIG_NUM_DDR_CONTROLLERS > 1) + uint32_t cs0_config = in_be32(&ddr->cs0_config); +#endif + uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg); + int cas_lat; + +#if CONFIG_NUM_DDR_CONTROLLERS >= 2 + if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { + ddr = (void __iomem *)CONFIG_SYS_FSL_DDR2_ADDR; + sdram_cfg = in_be32(&ddr->sdram_cfg); + } +#endif +#if CONFIG_NUM_DDR_CONTROLLERS >= 3 + if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { + ddr = (void __iomem *)CONFIG_SYS_FSL_DDR3_ADDR; + sdram_cfg = in_be32(&ddr->sdram_cfg); + } +#endif + puts(" (DDR"); + switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> + SDRAM_CFG_SDRAM_TYPE_SHIFT) { + case SDRAM_TYPE_DDR1: + puts("1"); + break; + case SDRAM_TYPE_DDR2: + puts("2"); + break; + case SDRAM_TYPE_DDR3: + puts("3"); + break; + default: + puts("?"); + break; + } + + if (sdram_cfg & SDRAM_CFG_32_BE) + puts(", 32-bit"); + else if (sdram_cfg & SDRAM_CFG_16_BE) + puts(", 16-bit"); + else + puts(", 64-bit"); + + /* Calculate CAS latency based on timing cfg values */ + cas_lat = ((in_be32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1; + if ((in_be32(&ddr->timing_cfg_3) >> 12) & 1) + cas_lat += (8 << 1); + printf(", CL=%d", cas_lat >> 1); + if (cas_lat & 0x1) + puts(".5"); + + if (sdram_cfg & SDRAM_CFG_ECC_EN) + puts(", ECC on)"); + else + puts(", ECC off)"); + +#if (CONFIG_NUM_DDR_CONTROLLERS == 3) +#ifdef CONFIG_E6500 + if (*mcintl3r & 0x80000000) { + puts("\n"); + puts(" DDR Controller Interleaving Mode: "); + switch (*mcintl3r & 0x1f) { + case FSL_DDR_3WAY_1KB_INTERLEAVING: + puts("3-way 1KB"); + break; + case FSL_DDR_3WAY_4KB_INTERLEAVING: + puts("3-way 4KB"); + break; + case FSL_DDR_3WAY_8KB_INTERLEAVING: + puts("3-way 8KB"); + break; + default: + puts("3-way UNKNOWN"); + break; + } + } +#endif +#endif +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) + if (cs0_config & 0x20000000) { + puts("\n"); + puts(" DDR Controller Interleaving Mode: "); + + switch ((cs0_config >> 24) & 0xf) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + puts("cache line"); + break; + case FSL_DDR_PAGE_INTERLEAVING: + puts("page"); + break; + case FSL_DDR_BANK_INTERLEAVING: + puts("bank"); + break; + case FSL_DDR_SUPERBANK_INTERLEAVING: + puts("super-bank"); + break; + default: + puts("invalid"); + break; + } + } +#endif + + if ((sdram_cfg >> 8) & 0x7f) { + puts("\n"); + puts(" DDR Chip-Select Interleaving Mode: "); + switch(sdram_cfg >> 8 & 0x7f) { + case FSL_DDR_CS0_CS1_CS2_CS3: + puts("CS0+CS1+CS2+CS3"); + break; + case FSL_DDR_CS0_CS1: + puts("CS0+CS1"); + break; + case FSL_DDR_CS2_CS3: + puts("CS2+CS3"); + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + puts("CS0+CS1 and CS2+CS3"); + break; + default: + puts("invalid"); + break; + } + } +} diff --git a/include/common_timing_params.h b/include/common_timing_params.h new file mode 100644 index 0000000000..76338d4e6c --- /dev/null +++ b/include/common_timing_params.h @@ -0,0 +1,57 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef COMMON_TIMING_PARAMS_H +#define COMMON_TIMING_PARAMS_H + +typedef struct { + /* parameters to constrict */ + + unsigned int tckmin_x_ps; + unsigned int tckmax_ps; + unsigned int tckmax_max_ps; + unsigned int trcd_ps; + unsigned int trp_ps; + unsigned int tras_ps; + + unsigned int twr_ps; /* maximum = 63750 ps */ + unsigned int twtr_ps; /* maximum = 63750 ps */ + unsigned int trfc_ps; /* maximum = 255 ns + 256 ns + .75 ns + = 511750 ps */ + + unsigned int trrd_ps; /* maximum = 63750 ps */ + unsigned int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ + + unsigned int refresh_rate_ps; + unsigned int extended_op_srt; + + unsigned int tis_ps; /* byte 32, spd->ca_setup */ + unsigned int tih_ps; /* byte 33, spd->ca_hold */ + unsigned int tds_ps; /* byte 34, spd->data_setup */ + unsigned int tdh_ps; /* byte 35, spd->data_hold */ + unsigned int trtp_ps; /* byte 38, spd->trtp */ + unsigned int tdqsq_max_ps; /* byte 44, spd->tdqsq */ + unsigned int tqhs_ps; /* byte 45, spd->tqhs */ + + unsigned int ndimms_present; + unsigned int lowest_common_SPD_caslat; + unsigned int highest_common_derated_caslat; + unsigned int additive_latency; + unsigned int all_dimms_burst_lengths_bitmask; + unsigned int all_dimms_registered; + unsigned int all_dimms_unbuffered; + unsigned int all_dimms_ecc_capable; + + unsigned long long total_mem; + unsigned long long base_address; + + /* DDR3 RDIMM */ + unsigned char rcw[16]; /* Register Control Word 0-15 */ +} common_timing_params_t; + +#endif diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h index 268f66ec0e..b2a5c19e0e 100644 --- a/include/configs/B4860QDS.h +++ b/include/configs/B4860QDS.h @@ -193,7 +193,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_DDR_SPD #define CONFIG_SYS_DDR_RAW_TIMING -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SYS_SPD_BUS_NUM 0 diff --git a/include/configs/BSC9131RDB.h b/include/configs/BSC9131RDB.h index 036f264c97..499d8c2054 100644 --- a/include/configs/BSC9131RDB.h +++ b/include/configs/BSC9131RDB.h @@ -80,7 +80,7 @@ #define CONFIG_SYS_MEMTEST_END 0x01ffffff /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #undef CONFIG_SYS_DDR_RAW_TIMING #undef CONFIG_DDR_SPD #define CONFIG_SYS_SPD_BUS_NUM 0 diff --git a/include/configs/BSC9132QDS.h b/include/configs/BSC9132QDS.h index 75889b3574..a6601fee86 100644 --- a/include/configs/BSC9132QDS.h +++ b/include/configs/BSC9132QDS.h @@ -134,7 +134,7 @@ #define CONFIG_SYS_MEMTEST_END 0x01ffffff /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS1 0x54 /* I2C access */ #define SPD_EEPROM_ADDRESS2 0x56 /* I2C access */ diff --git a/include/configs/C29XPCIE.h b/include/configs/C29XPCIE.h index 08156c531d..f173b07b4d 100644 --- a/include/configs/C29XPCIE.h +++ b/include/configs/C29XPCIE.h @@ -103,7 +103,7 @@ #define CONFIG_PANIC_HANG /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_DDR_SPD #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS 0x50 diff --git a/include/configs/HWW1U1A.h b/include/configs/HWW1U1A.h index f3f2136668..bbfee7d308 100644 --- a/include/configs/HWW1U1A.h +++ b/include/configs/HWW1U1A.h @@ -255,7 +255,7 @@ /* -------------------------------------------------------------------- */ /* FreeScale DDR2/3 SDRAM Controller */ -#define CONFIG_FSL_DDR2 /* Our SDRAM slot is DDR2 */ +#define CONFIG_SYS_FSL_DDR2 /* Our SDRAM slot is DDR2 */ #define CONFIG_DDR_ECC /* Enable ECC by default */ #define CONFIG_DDR_SPD /* Detect DDR config from SPD EEPROM */ #define CONFIG_SPD_EEPROM /* ...why 2 config variables for this? */ diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h index 3f742a2bba..a80a6966bf 100644 --- a/include/configs/MPC8349EMDS.h +++ b/include/configs/MPC8349EMDS.h @@ -62,11 +62,11 @@ #define CONFIG_SPD_EEPROM /* use SPD EEPROM for DDR setup*/ /* - * define CONFIG_FSL_DDR2 to use unified DDR driver + * define CONFIG_SYS_FSL_DDR2 to use unified DDR driver * undefine it to use old spd_sdram.c */ -#define CONFIG_FSL_DDR2 -#ifdef CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 +#ifdef CONFIG_SYS_FSL_DDR2 #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS1 0x52 #define SPD_EEPROM_ADDRESS2 0x51 diff --git a/include/configs/MPC8536DS.h b/include/configs/MPC8536DS.h index 8197f89e4e..9ab1bc106b 100644 --- a/include/configs/MPC8536DS.h +++ b/include/configs/MPC8536DS.h @@ -122,7 +122,7 @@ /* DDR Setup */ #define CONFIG_VERY_BIG_RAM -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8540ADS.h b/include/configs/MPC8540ADS.h index 66893688e6..046b14bdda 100644 --- a/include/configs/MPC8540ADS.h +++ b/include/configs/MPC8540ADS.h @@ -78,7 +78,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/MPC8541CDS.h b/include/configs/MPC8541CDS.h index e24c597453..eca3b537b4 100644 --- a/include/configs/MPC8541CDS.h +++ b/include/configs/MPC8541CDS.h @@ -51,7 +51,7 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h index 2e76df681b..8132ec055b 100644 --- a/include/configs/MPC8544DS.h +++ b/include/configs/MPC8544DS.h @@ -63,7 +63,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h index 9ff048af6d..6acd54db85 100644 --- a/include/configs/MPC8548CDS.h +++ b/include/configs/MPC8548CDS.h @@ -75,7 +75,7 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8555CDS.h b/include/configs/MPC8555CDS.h index 7f0f927ea1..5ffdd01629 100644 --- a/include/configs/MPC8555CDS.h +++ b/include/configs/MPC8555CDS.h @@ -51,7 +51,7 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h index b7c4a60309..bb9ae2dcb5 100644 --- a/include/configs/MPC8560ADS.h +++ b/include/configs/MPC8560ADS.h @@ -75,7 +75,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h index c9a15395c3..7406ac3be8 100644 --- a/include/configs/MPC8568MDS.h +++ b/include/configs/MPC8568MDS.h @@ -60,7 +60,7 @@ extern unsigned long get_clock_freq(void); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8569MDS.h b/include/configs/MPC8569MDS.h index 341f6a89b4..df5572b3a8 100644 --- a/include/configs/MPC8569MDS.h +++ b/include/configs/MPC8569MDS.h @@ -98,7 +98,7 @@ extern unsigned long get_clock_freq(void); #endif /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index c7511449ea..afb195fe4e 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -106,7 +106,7 @@ /* DDR Setup */ #define CONFIG_VERY_BIG_RAM -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index 97f5c877e1..41ebe31dd4 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -92,7 +92,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS CONFIG_SYS_CCSRBAR_PHYS_LOW /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD for DDR */ #define CONFIG_DDR_SPD diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 8ed5050766..0e666bac01 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -108,7 +108,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); /* * DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h index 50c365a5b1..eab386add4 100644 --- a/include/configs/P1010RDB.h +++ b/include/configs/P1010RDB.h @@ -178,7 +178,7 @@ #define CONFIG_PANIC_HANG /* do not reset board on panic */ /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_DDR_RAW_TIMING #define CONFIG_DDR_SPD #define CONFIG_SYS_SPD_BUS_NUM 1 diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h index 1470526d0b..262c3e5f1f 100644 --- a/include/configs/P1022DS.h +++ b/include/configs/P1022DS.h @@ -177,7 +177,7 @@ /* DDR Setup */ #define CONFIG_DDR_SPD #define CONFIG_VERY_BIG_RAM -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #ifdef CONFIG_DDR_ECC #define CONFIG_ECC_INIT_VIA_DDRCONTROLLER diff --git a/include/configs/P1023RDB.h b/include/configs/P1023RDB.h index e49523e940..7de6814a03 100644 --- a/include/configs/P1023RDB.h +++ b/include/configs/P1023RDB.h @@ -74,7 +74,7 @@ extern unsigned long get_clock_freq(void); #define CONFIG_CHIP_SELECTS_PER_CTRL 1 #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SYS_SDRAM_SIZE 512u /* DDR is 512M */ #define CONFIG_SYS_SPD_BUS_NUM 0 diff --git a/include/configs/P1_P2_RDB.h b/include/configs/P1_P2_RDB.h index 282f5c1a12..b592c1966a 100644 --- a/include/configs/P1_P2_RDB.h +++ b/include/configs/P1_P2_RDB.h @@ -141,7 +141,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #endif /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #undef CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ diff --git a/include/configs/P2020COME.h b/include/configs/P2020COME.h index 9cc219e5a8..15d2a43cd0 100644 --- a/include/configs/P2020COME.h +++ b/include/configs/P2020COME.h @@ -105,7 +105,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/P2020DS.h b/include/configs/P2020DS.h index 8a29eaa507..9d3d9b33e5 100644 --- a/include/configs/P2020DS.h +++ b/include/configs/P2020DS.h @@ -109,9 +109,9 @@ /* DDR Setup */ #define CONFIG_VERY_BIG_RAM #ifdef CONFIG_DDR2 -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #else -#define CONFIG_FSL_DDR3 1 +#define CONFIG_SYS_FSL_DDR3 1 #endif /* ECC will be enabled based on perf_mode environment variable */ diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h index 0df6f1a2d9..b238574b5d 100644 --- a/include/configs/P2041RDB.h +++ b/include/configs/P2041RDB.h @@ -175,7 +175,7 @@ unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_CHIP_SELECTS_PER_CTRL (4 * CONFIG_DIMM_SLOTS_PER_CTLR) #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS 0x52 diff --git a/include/configs/T1040QDS.h b/include/configs/T1040QDS.h index 7c6bec8f76..43a5778004 100644 --- a/include/configs/T1040QDS.h +++ b/include/configs/T1040QDS.h @@ -170,7 +170,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_CHIP_SELECTS_PER_CTRL (4 * CONFIG_DIMM_SLOTS_PER_CTLR) #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SYS_SPD_BUS_NUM 0 diff --git a/include/configs/T1040RDB.h b/include/configs/T1040RDB.h index 620387fcd0..79312311d8 100644 --- a/include/configs/T1040RDB.h +++ b/include/configs/T1040RDB.h @@ -156,7 +156,7 @@ #define CONFIG_DDR_SPD #define CONFIG_SYS_DDR_RAW_TIMING -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS 0x51 diff --git a/include/configs/T1042RDB_PI.h b/include/configs/T1042RDB_PI.h index 4b023f9e84..eff08e3804 100644 --- a/include/configs/T1042RDB_PI.h +++ b/include/configs/T1042RDB_PI.h @@ -156,7 +156,7 @@ #define CONFIG_DDR_SPD #define CONFIG_SYS_DDR_RAW_TIMING -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SPD_BUS_NUM 0 #define SPD_EEPROM_ADDRESS 0x51 diff --git a/include/configs/controlcenterd.h b/include/configs/controlcenterd.h index 413f0867f4..46d4f9865f 100644 --- a/include/configs/controlcenterd.h +++ b/include/configs/controlcenterd.h @@ -138,7 +138,7 @@ #define CONFIG_SYS_SDRAM_SIZE 1024 #define CONFIG_VERY_BIG_RAM -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_NUM_DDR_CONTROLLERS 1 #define CONFIG_DIMM_SLOTS_PER_CTLR 1 #define CONFIG_CHIP_SELECTS_PER_CTRL (2 * CONFIG_DIMM_SLOTS_PER_CTLR) diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h index 562caa5845..665295c1a2 100644 --- a/include/configs/corenet_ds.h +++ b/include/configs/corenet_ds.h @@ -173,7 +173,7 @@ #define CONFIG_CHIP_SELECTS_PER_CTRL (4 * CONFIG_DIMM_SLOTS_PER_CTLR) #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SPD_BUS_NUM 1 #define SPD_EEPROM_ADDRESS1 0x51 diff --git a/include/configs/km/kmp204x-common.h b/include/configs/km/kmp204x-common.h index 2d5320b5cd..7700b38c2d 100644 --- a/include/configs/km/kmp204x-common.h +++ b/include/configs/km/kmp204x-common.h @@ -111,7 +111,7 @@ unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_CHIP_SELECTS_PER_CTRL (4 * CONFIG_DIMM_SLOTS_PER_CTLR) #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SYS_SPD_BUS_NUM 0 diff --git a/include/configs/mpq101.h b/include/configs/mpq101.h index 6d0d392b77..ec09e15dbf 100644 --- a/include/configs/mpq101.h +++ b/include/configs/mpq101.h @@ -52,7 +52,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #define CONFIG_ECC_INIT_VIA_DDRCONTROLLER /* DDR controller or DMA? */ diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h index 91a678212d..57ed019952 100644 --- a/include/configs/p1_p2_rdb_pc.h +++ b/include/configs/p1_p2_rdb_pc.h @@ -325,7 +325,7 @@ #endif /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_DDR_RAW_TIMING #define CONFIG_DDR_SPD #define CONFIG_SYS_SPD_BUS_NUM 1 diff --git a/include/configs/p1_twr.h b/include/configs/p1_twr.h index 76189e136f..9837100e31 100644 --- a/include/configs/p1_twr.h +++ b/include/configs/p1_twr.h @@ -89,7 +89,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy); #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SYS_SDRAM_SIZE_LAW LAW_SIZE_512M #define CONFIG_CHIP_SELECTS_PER_CTRL 1 diff --git a/include/configs/sbc8548.h b/include/configs/sbc8548.h index 6d970608f2..bdb8eb529d 100644 --- a/include/configs/sbc8548.h +++ b/include/configs/sbc8548.h @@ -102,7 +102,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #undef CONFIG_DDR_ECC /* only for ECC DDR module */ /* diff --git a/include/configs/socrates.h b/include/configs/socrates.h index b6fbe23706..0e6b86412d 100644 --- a/include/configs/socrates.h +++ b/include/configs/socrates.h @@ -80,7 +80,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/stxgp3.h b/include/configs/stxgp3.h index 9b3f0cc69f..ee1f1f3ed0 100644 --- a/include/configs/stxgp3.h +++ b/include/configs/stxgp3.h @@ -98,7 +98,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/stxssa.h b/include/configs/stxssa.h index 805814f4fb..63dd767047 100644 --- a/include/configs/stxssa.h +++ b/include/configs/stxssa.h @@ -112,7 +112,7 @@ #define CONFIG_SYS_CCSRBAR_PHYS_LOW CONFIG_SYS_CCSRBAR /* DDR Setup */ -#define CONFIG_FSL_DDR1 +#define CONFIG_SYS_FSL_DDR1 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup*/ #define CONFIG_DDR_SPD #undef CONFIG_FSL_DDR_INTERACTIVE diff --git a/include/configs/t4qds.h b/include/configs/t4qds.h index 3f54f1423e..d9b0ed07d6 100644 --- a/include/configs/t4qds.h +++ b/include/configs/t4qds.h @@ -87,7 +87,7 @@ #define CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE #define CONFIG_DDR_SPD -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 /* diff --git a/include/configs/xpedite517x.h b/include/configs/xpedite517x.h index 4738c23350..88d7f88cc0 100644 --- a/include/configs/xpedite517x.h +++ b/include/configs/xpedite517x.h @@ -40,7 +40,7 @@ /* * DDR config */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD #define CONFIG_MEM_INIT_VALUE 0xdeadbeef diff --git a/include/configs/xpedite520x.h b/include/configs/xpedite520x.h index 33428803eb..f39d6f9105 100644 --- a/include/configs/xpedite520x.h +++ b/include/configs/xpedite520x.h @@ -39,7 +39,7 @@ /* * DDR config */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/xpedite537x.h b/include/configs/xpedite537x.h index 9da845d9a2..e1bdf90de4 100644 --- a/include/configs/xpedite537x.h +++ b/include/configs/xpedite537x.h @@ -49,7 +49,7 @@ /* * DDR config */ -#define CONFIG_FSL_DDR2 +#define CONFIG_SYS_FSL_DDR2 #undef CONFIG_FSL_DDR_INTERACTIVE #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD diff --git a/include/configs/xpedite550x.h b/include/configs/xpedite550x.h index 4137cc9208..2328c7a62e 100644 --- a/include/configs/xpedite550x.h +++ b/include/configs/xpedite550x.h @@ -49,7 +49,7 @@ /* * DDR config */ -#define CONFIG_FSL_DDR3 +#define CONFIG_SYS_FSL_DDR3 #define CONFIG_SPD_EEPROM /* Use SPD EEPROM for DDR setup */ #define CONFIG_DDR_SPD #define CONFIG_MEM_INIT_VALUE 0xdeadbeef diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h new file mode 100644 index 0000000000..e03f9db5f2 --- /dev/null +++ b/include/fsl_ddr.h @@ -0,0 +1,105 @@ +/* + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef FSL_DDR_MAIN_H +#define FSL_DDR_MAIN_H + +#include +#include + +#include + +#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) +/* + * Bind the main DDR setup driver's generic names + * to this specific DDR technology. + */ +static __inline__ int +compute_dimm_parameters(const generic_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number) +{ + return ddr_compute_dimm_parameters(spd, pdimm, dimm_number); +} +#endif + +/* + * Data Structures + * + * All data structures have to be on the stack + */ +#define CONFIG_SYS_NUM_DDR_CTLRS CONFIG_NUM_DDR_CONTROLLERS +#define CONFIG_SYS_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR + +typedef struct { + generic_spd_eeprom_t + spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR]; + struct dimm_params_s + dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR]; + memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS]; + common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS]; + fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS]; +} fsl_ddr_info_t; + +/* Compute steps */ +#define STEP_GET_SPD (1 << 0) +#define STEP_COMPUTE_DIMM_PARMS (1 << 1) +#define STEP_COMPUTE_COMMON_PARMS (1 << 2) +#define STEP_GATHER_OPTS (1 << 3) +#define STEP_ASSIGN_ADDRESSES (1 << 4) +#define STEP_COMPUTE_REGS (1 << 5) +#define STEP_PROGRAM_REGS (1 << 6) +#define STEP_ALL 0xFFF + +unsigned long long +fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, + unsigned int size_only); + +const char *step_to_string(unsigned int step); + +unsigned int compute_fsl_memctl_config_regs(const memctl_options_t *popts, + fsl_ddr_cfg_regs_t *ddr, + const common_timing_params_t *common_dimm, + const dimm_params_t *dimm_parameters, + unsigned int dbw_capacity_adjust, + unsigned int size_only); +unsigned int compute_lowest_common_dimm_parameters( + const dimm_params_t *dimm_params, + common_timing_params_t *outpdimm, + unsigned int number_of_dimms); +unsigned int populate_memctl_options(int all_dimms_registered, + memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num); +void check_interleaving_options(fsl_ddr_info_t *pinfo); + +unsigned int mclk_to_picos(unsigned int mclk); +unsigned int get_memory_clk_period_ps(void); +unsigned int picos_to_mclk(unsigned int picos); +void fsl_ddr_set_lawbar( + const common_timing_params_t *memctl_common_params, + unsigned int memctl_interleaved, + unsigned int ctrl_num); + +int fsl_ddr_interactive_env_var_exists(void); +unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set); +void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, + unsigned int ctrl_num); + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr); + +/* processor specific function */ +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step); + +/* board specific function */ +int fsl_ddr_get_dimm_params(dimm_params_t *pdimm, + unsigned int controller_number, + unsigned int dimm_number); +#endif diff --git a/include/fsl_ddr_dimm_params.h b/include/fsl_ddr_dimm_params.h new file mode 100644 index 0000000000..99a72bc6e1 --- /dev/null +++ b/include/fsl_ddr_dimm_params.h @@ -0,0 +1,101 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef DDR2_DIMM_PARAMS_H +#define DDR2_DIMM_PARAMS_H + +#define EDC_DATA_PARITY 1 +#define EDC_ECC 2 +#define EDC_AC_PARITY 4 + +/* Parameters for a DDR2 dimm computed from the SPD */ +typedef struct dimm_params_s { + + /* DIMM organization parameters */ + char mpart[19]; /* guaranteed null terminated */ + + unsigned int n_ranks; + unsigned long long rank_density; + unsigned long long capacity; + unsigned int data_width; + unsigned int primary_sdram_width; + unsigned int ec_sdram_width; + unsigned int registered_dimm; + unsigned int device_width; /* x4, x8, x16 components */ + + /* SDRAM device parameters */ + unsigned int n_row_addr; + unsigned int n_col_addr; + unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */ + unsigned int n_banks_per_sdram_device; + unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */ + unsigned int row_density; + + /* used in computing base address of DIMMs */ + unsigned long long base_address; + /* mirrored DIMMs */ + unsigned int mirrored_dimm; /* only for ddr3 */ + + /* DIMM timing parameters */ + + unsigned int mtb_ps; /* medium timebase ps, only for ddr3 */ + unsigned int ftb_10th_ps; /* fine timebase, in 1/10 ps, only for ddr3 */ + unsigned int taa_ps; /* minimum CAS latency time, only for ddr3 */ + unsigned int tfaw_ps; /* four active window delay, only for ddr3 */ + + /* + * SDRAM clock periods + * The range for these are 1000-10000 so a short should be sufficient + */ + unsigned int tckmin_x_ps; + unsigned int tckmin_x_minus_1_ps; + unsigned int tckmin_x_minus_2_ps; + unsigned int tckmax_ps; + + /* SPD-defined CAS latencies */ + unsigned int caslat_x; + unsigned int caslat_x_minus_1; + unsigned int caslat_x_minus_2; + + unsigned int caslat_lowest_derated; /* Derated CAS latency */ + + /* basic timing parameters */ + unsigned int trcd_ps; + unsigned int trp_ps; + unsigned int tras_ps; + + unsigned int twr_ps; /* maximum = 63750 ps */ + unsigned int twtr_ps; /* maximum = 63750 ps */ + unsigned int trfc_ps; /* max = 255 ns + 256 ns + .75 ns + = 511750 ps */ + + unsigned int trrd_ps; /* maximum = 63750 ps */ + unsigned int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ + + unsigned int refresh_rate_ps; + unsigned int extended_op_srt; + + /* DDR3 doesn't need these as below */ + unsigned int tis_ps; /* byte 32, spd->ca_setup */ + unsigned int tih_ps; /* byte 33, spd->ca_hold */ + unsigned int tds_ps; /* byte 34, spd->data_setup */ + unsigned int tdh_ps; /* byte 35, spd->data_hold */ + unsigned int trtp_ps; /* byte 38, spd->trtp */ + unsigned int tdqsq_max_ps; /* byte 44, spd->tdqsq */ + unsigned int tqhs_ps; /* byte 45, spd->tqhs */ + + /* DDR3 RDIMM */ + unsigned char rcw[16]; /* Register Control Word 0-15 */ +} dimm_params_t; + +extern unsigned int ddr_compute_dimm_parameters( + const generic_spd_eeprom_t *spd, + dimm_params_t *pdimm, + unsigned int dimm_number); + +#endif diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h new file mode 100644 index 0000000000..16cccc7708 --- /dev/null +++ b/include/fsl_ddr_sdram.h @@ -0,0 +1,377 @@ +/* + * Copyright 2008-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#ifndef FSL_DDR_MEMCTL_H +#define FSL_DDR_MEMCTL_H + +/* + * Pick a basic DDR Technology. + */ +#include + +#define SDRAM_TYPE_DDR1 2 +#define SDRAM_TYPE_DDR2 3 +#define SDRAM_TYPE_LPDDR1 6 +#define SDRAM_TYPE_DDR3 7 + +#define DDR_BL4 4 /* burst length 4 */ +#define DDR_BC4 DDR_BL4 /* burst chop for ddr3 */ +#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */ +#define DDR_BL8 8 /* burst length 8 */ + +#define DDR3_RTT_OFF 0 +#define DDR3_RTT_60_OHM 1 /* RTT_Nom = RZQ/4 */ +#define DDR3_RTT_120_OHM 2 /* RTT_Nom = RZQ/2 */ +#define DDR3_RTT_40_OHM 3 /* RTT_Nom = RZQ/6 */ +#define DDR3_RTT_20_OHM 4 /* RTT_Nom = RZQ/12 */ +#define DDR3_RTT_30_OHM 5 /* RTT_Nom = RZQ/8 */ + +#define DDR2_RTT_OFF 0 +#define DDR2_RTT_75_OHM 1 +#define DDR2_RTT_150_OHM 2 +#define DDR2_RTT_50_OHM 3 + +#if defined(CONFIG_SYS_FSL_DDR1) +#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (1) +typedef ddr1_spd_eeprom_t generic_spd_eeprom_t; +#ifndef CONFIG_FSL_SDRAM_TYPE +#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR1 +#endif +#elif defined(CONFIG_SYS_FSL_DDR2) +#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) +typedef ddr2_spd_eeprom_t generic_spd_eeprom_t; +#ifndef CONFIG_FSL_SDRAM_TYPE +#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR2 +#endif +#elif defined(CONFIG_SYS_FSL_DDR3) +#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) /* FIXME */ +typedef ddr3_spd_eeprom_t generic_spd_eeprom_t; +#ifndef CONFIG_FSL_SDRAM_TYPE +#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR3 +#endif +#endif /* #if defined(CONFIG_SYS_FSL_DDR1) */ + +#define FSL_DDR_ODT_NEVER 0x0 +#define FSL_DDR_ODT_CS 0x1 +#define FSL_DDR_ODT_ALL_OTHER_CS 0x2 +#define FSL_DDR_ODT_OTHER_DIMM 0x3 +#define FSL_DDR_ODT_ALL 0x4 +#define FSL_DDR_ODT_SAME_DIMM 0x5 +#define FSL_DDR_ODT_CS_AND_OTHER_DIMM 0x6 +#define FSL_DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7 + +/* define bank(chip select) interleaving mode */ +#define FSL_DDR_CS0_CS1 0x40 +#define FSL_DDR_CS2_CS3 0x20 +#define FSL_DDR_CS0_CS1_AND_CS2_CS3 (FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3) +#define FSL_DDR_CS0_CS1_CS2_CS3 (FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04) + +/* define memory controller interleaving mode */ +#define FSL_DDR_CACHE_LINE_INTERLEAVING 0x0 +#define FSL_DDR_PAGE_INTERLEAVING 0x1 +#define FSL_DDR_BANK_INTERLEAVING 0x2 +#define FSL_DDR_SUPERBANK_INTERLEAVING 0x3 +#define FSL_DDR_3WAY_1KB_INTERLEAVING 0xA +#define FSL_DDR_3WAY_4KB_INTERLEAVING 0xC +#define FSL_DDR_3WAY_8KB_INTERLEAVING 0xD +/* placeholder for 4-way interleaving */ +#define FSL_DDR_4WAY_1KB_INTERLEAVING 0x1A +#define FSL_DDR_4WAY_4KB_INTERLEAVING 0x1C +#define FSL_DDR_4WAY_8KB_INTERLEAVING 0x1D + +#define SDRAM_CS_CONFIG_EN 0x80000000 + +/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration + */ +#define SDRAM_CFG_MEM_EN 0x80000000 +#define SDRAM_CFG_SREN 0x40000000 +#define SDRAM_CFG_ECC_EN 0x20000000 +#define SDRAM_CFG_RD_EN 0x10000000 +#define SDRAM_CFG_SDRAM_TYPE_DDR1 0x02000000 +#define SDRAM_CFG_SDRAM_TYPE_DDR2 0x03000000 +#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000 +#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24 +#define SDRAM_CFG_DYN_PWR 0x00200000 +#define SDRAM_CFG_DBW_MASK 0x00180000 +#define SDRAM_CFG_DBW_SHIFT 19 +#define SDRAM_CFG_32_BE 0x00080000 +#define SDRAM_CFG_16_BE 0x00100000 +#define SDRAM_CFG_8_BE 0x00040000 +#define SDRAM_CFG_NCAP 0x00020000 +#define SDRAM_CFG_2T_EN 0x00008000 +#define SDRAM_CFG_BI 0x00000001 + +#define SDRAM_CFG2_D_INIT 0x00000010 +#define SDRAM_CFG2_ODT_CFG_MASK 0x00600000 +#define SDRAM_CFG2_ODT_NEVER 0 +#define SDRAM_CFG2_ODT_ONLY_WRITE 1 +#define SDRAM_CFG2_ODT_ONLY_READ 2 +#define SDRAM_CFG2_ODT_ALWAYS 3 + +#define TIMING_CFG_2_CPO_MASK 0x0F800000 + +#if defined(CONFIG_P4080) +#define RD_TO_PRE_MASK 0xf +#define RD_TO_PRE_SHIFT 13 +#define WR_DATA_DELAY_MASK 0xf +#define WR_DATA_DELAY_SHIFT 9 +#else +#define RD_TO_PRE_MASK 0x7 +#define RD_TO_PRE_SHIFT 13 +#define WR_DATA_DELAY_MASK 0x7 +#define WR_DATA_DELAY_SHIFT 10 +#endif + +/* DDR_MD_CNTL */ +#define MD_CNTL_MD_EN 0x80000000 +#define MD_CNTL_CS_SEL_CS0 0x00000000 +#define MD_CNTL_CS_SEL_CS1 0x10000000 +#define MD_CNTL_CS_SEL_CS2 0x20000000 +#define MD_CNTL_CS_SEL_CS3 0x30000000 +#define MD_CNTL_CS_SEL_CS0_CS1 0x40000000 +#define MD_CNTL_CS_SEL_CS2_CS3 0x50000000 +#define MD_CNTL_MD_SEL_MR 0x00000000 +#define MD_CNTL_MD_SEL_EMR 0x01000000 +#define MD_CNTL_MD_SEL_EMR2 0x02000000 +#define MD_CNTL_MD_SEL_EMR3 0x03000000 +#define MD_CNTL_SET_REF 0x00800000 +#define MD_CNTL_SET_PRE 0x00400000 +#define MD_CNTL_CKE_CNTL_LOW 0x00100000 +#define MD_CNTL_CKE_CNTL_HIGH 0x00200000 +#define MD_CNTL_WRCW 0x00080000 +#define MD_CNTL_MD_VALUE(x) (x & 0x0000FFFF) + +/* DDR_CDR1 */ +#define DDR_CDR1_DHC_EN 0x80000000 +#define DDR_CDR1_ODT_SHIFT 17 +#define DDR_CDR1_ODT_MASK 0x6 +#define DDR_CDR2_ODT_MASK 0x1 +#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT) +#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK) + +#if (defined(CONFIG_SYS_FSL_DDR_VER) && \ + (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)) +#define DDR_CDR_ODT_OFF 0x0 +#define DDR_CDR_ODT_120ohm 0x1 +#define DDR_CDR_ODT_180ohm 0x2 +#define DDR_CDR_ODT_75ohm 0x3 +#define DDR_CDR_ODT_110ohm 0x4 +#define DDR_CDR_ODT_60hm 0x5 +#define DDR_CDR_ODT_70ohm 0x6 +#define DDR_CDR_ODT_47ohm 0x7 +#else +#define DDR_CDR_ODT_75ohm 0x0 +#define DDR_CDR_ODT_55ohm 0x1 +#define DDR_CDR_ODT_60ohm 0x2 +#define DDR_CDR_ODT_50ohm 0x3 +#define DDR_CDR_ODT_150ohm 0x4 +#define DDR_CDR_ODT_43ohm 0x5 +#define DDR_CDR_ODT_120ohm 0x6 +#endif + +/* Record of register values computed */ +typedef struct fsl_ddr_cfg_regs_s { + struct { + unsigned int bnds; + unsigned int config; + unsigned int config_2; + } cs[CONFIG_CHIP_SELECTS_PER_CTRL]; + unsigned int timing_cfg_3; + unsigned int timing_cfg_0; + unsigned int timing_cfg_1; + unsigned int timing_cfg_2; + unsigned int ddr_sdram_cfg; + unsigned int ddr_sdram_cfg_2; + unsigned int ddr_sdram_mode; + unsigned int ddr_sdram_mode_2; + unsigned int ddr_sdram_mode_3; + unsigned int ddr_sdram_mode_4; + unsigned int ddr_sdram_mode_5; + unsigned int ddr_sdram_mode_6; + unsigned int ddr_sdram_mode_7; + unsigned int ddr_sdram_mode_8; + unsigned int ddr_sdram_md_cntl; + unsigned int ddr_sdram_interval; + unsigned int ddr_data_init; + unsigned int ddr_sdram_clk_cntl; + unsigned int ddr_init_addr; + unsigned int ddr_init_ext_addr; + unsigned int timing_cfg_4; + unsigned int timing_cfg_5; + unsigned int ddr_zq_cntl; + unsigned int ddr_wrlvl_cntl; + unsigned int ddr_wrlvl_cntl_2; + unsigned int ddr_wrlvl_cntl_3; + unsigned int ddr_sr_cntr; + unsigned int ddr_sdram_rcw_1; + unsigned int ddr_sdram_rcw_2; + unsigned int ddr_eor; + unsigned int ddr_cdr1; + unsigned int ddr_cdr2; + unsigned int err_disable; + unsigned int err_int_en; + unsigned int debug[32]; +} fsl_ddr_cfg_regs_t; + +typedef struct memctl_options_partial_s { + unsigned int all_dimms_ecc_capable; + unsigned int all_dimms_tckmax_ps; + unsigned int all_dimms_burst_lengths_bitmask; + unsigned int all_dimms_registered; + unsigned int all_dimms_unbuffered; + /* unsigned int lowest_common_SPD_caslat; */ + unsigned int all_dimms_minimum_trcd_ps; +} memctl_options_partial_t; + +#define DDR_DATA_BUS_WIDTH_64 0 +#define DDR_DATA_BUS_WIDTH_32 1 +#define DDR_DATA_BUS_WIDTH_16 2 +/* + * Generalized parameters for memory controller configuration, + * might be a little specific to the FSL memory controller + */ +typedef struct memctl_options_s { + /* + * Memory organization parameters + * + * if DIMM is present in the system + * where DIMMs are with respect to chip select + * where chip selects are with respect to memory boundaries + */ + unsigned int registered_dimm_en; /* use registered DIMM support */ + + /* Options local to a Chip Select */ + struct cs_local_opts_s { + unsigned int auto_precharge; + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; + } cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL]; + + /* Special configurations for chip select */ + unsigned int memctl_interleaving; + unsigned int memctl_interleaving_mode; + unsigned int ba_intlv_ctl; + unsigned int addr_hash; + + /* Operational mode parameters */ + unsigned int ecc_mode; /* Use ECC? */ + /* Initialize ECC using memory controller? */ + unsigned int ecc_init_using_memctl; + unsigned int dqs_config; /* Use DQS? maybe only with DDR2? */ + /* SREN - self-refresh during sleep */ + unsigned int self_refresh_in_sleep; + unsigned int dynamic_power; /* DYN_PWR */ + /* memory data width to use (16-bit, 32-bit, 64-bit) */ + unsigned int data_bus_width; + unsigned int burst_length; /* BL4, OTF and BL8 */ + /* On-The-Fly Burst Chop enable */ + unsigned int otf_burst_chop_en; + /* mirrior DIMMs for DDR3 */ + unsigned int mirrored_dimm; + unsigned int quad_rank_present; + unsigned int ap_en; /* address parity enable for RDIMM */ + unsigned int x4_en; /* enable x4 devices */ + + /* Global Timing Parameters */ + unsigned int cas_latency_override; + unsigned int cas_latency_override_value; + unsigned int use_derated_caslat; + unsigned int additive_latency_override; + unsigned int additive_latency_override_value; + + unsigned int clk_adjust; /* */ + unsigned int cpo_override; + unsigned int write_data_delay; /* DQS adjust */ + + unsigned int wrlvl_override; + unsigned int wrlvl_sample; /* Write leveling */ + unsigned int wrlvl_start; + unsigned int wrlvl_ctl_2; + unsigned int wrlvl_ctl_3; + + unsigned int half_strength_driver_enable; + unsigned int twot_en; + unsigned int threet_en; + unsigned int bstopre; + unsigned int tcke_clock_pulse_width_ps; /* tCKE */ + unsigned int tfaw_window_four_activates_ps; /* tFAW -- FOUR_ACT */ + + /* Rtt impedance */ + unsigned int rtt_override; /* rtt_override enable */ + unsigned int rtt_override_value; /* that is Rtt_Nom for DDR3 */ + unsigned int rtt_wr_override_value; /* this is Rtt_WR for DDR3 */ + + /* Automatic self refresh */ + unsigned int auto_self_refresh_en; + unsigned int sr_it; + /* ZQ calibration */ + unsigned int zq_en; + /* Write leveling */ + unsigned int wrlvl_en; + /* RCW override for RDIMM */ + unsigned int rcw_override; + unsigned int rcw_1; + unsigned int rcw_2; + /* control register 1 */ + unsigned int ddr_cdr1; + unsigned int ddr_cdr2; + + unsigned int trwt_override; + unsigned int trwt; /* read-to-write turnaround */ +} memctl_options_t; + +extern phys_size_t fsl_ddr_sdram(void); +extern phys_size_t fsl_ddr_sdram_size(void); +extern int fsl_use_spd(void); +extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step); +u32 fsl_ddr_get_intl3r(void); + +static void __board_assert_mem_reset(void) +{ +} + +static void __board_deassert_mem_reset(void) +{ +} + +void board_assert_mem_reset(void) + __attribute__((weak, alias("__board_assert_mem_reset"))); + +void board_deassert_mem_reset(void) + __attribute__((weak, alias("__board_deassert_mem_reset"))); + +static int __board_need_mem_reset(void) +{ + return 0; +} + +int board_need_mem_reset(void) + __attribute__((weak, alias("__board_need_mem_reset"))); + +/* + * The 85xx boards have a common prototype for fixed_sdram so put the + * declaration here. + */ +#ifdef CONFIG_MPC85xx +extern phys_size_t fixed_sdram(void); +#endif + +#if defined(CONFIG_DDR_ECC) +extern void ddr_enable_ecc(unsigned int dram_size); +#endif + + +typedef struct fixed_ddr_parm{ + int min_freq; + int max_freq; + fsl_ddr_cfg_regs_t *ddr_settings; +} fixed_ddr_parm_t; +#endif diff --git a/nand_spl/board/freescale/mpc8569mds/nand_boot.c b/nand_spl/board/freescale/mpc8569mds/nand_boot.c index 716b737ad2..ce7f6191ca 100644 --- a/nand_spl/board/freescale/mpc8569mds/nand_boot.c +++ b/nand_spl/board/freescale/mpc8569mds/nand_boot.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #define SYSCLK_66 66666666 diff --git a/nand_spl/board/freescale/p1023rds/nand_boot.c b/nand_spl/board/freescale/p1023rds/nand_boot.c index 94680004f7..58e6cbf289 100644 --- a/nand_spl/board/freescale/p1023rds/nand_boot.c +++ b/nand_spl/board/freescale/p1023rds/nand_boot.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -18,7 +18,7 @@ DECLARE_GLOBAL_DATA_PTR; /* Fixed sdram init -- doesn't use serial presence detect. */ void sdram_init(void) { - ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; + ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_FSL_DDR_ADDR; set_next_law(0, LAW_SIZE_2G, LAW_TRGT_IF_DDR_1); diff --git a/nand_spl/board/freescale/p1_p2_rdb/nand_boot.c b/nand_spl/board/freescale/p1_p2_rdb/nand_boot.c index 3244c8f6d9..f7e8438438 100644 --- a/nand_spl/board/freescale/p1_p2_rdb/nand_boot.c +++ b/nand_spl/board/freescale/p1_p2_rdb/nand_boot.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #define SYSCLK_MASK 0x00200000 diff --git a/spl/Makefile b/spl/Makefile index 29d7818df5..2a787afa4f 100644 --- a/spl/Makefile +++ b/spl/Makefile @@ -70,6 +70,7 @@ LIBS-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/ LIBS-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/ LIBS-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/ LIBS-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/ +LIBS-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += drivers/ddr/fsl/ LIBS-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/ LIBS-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/ LIBS-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/