diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-12-17 16:53:07 +0100 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-12-17 16:53:07 +0100 |
commit | cb5473205206c7f14cbb1e747f28ec75b48826e2 (patch) | |
tree | 8f4808d60917100b18a10b05230f7638a0a9bbcc /cpu/mpc8xxx/ddr | |
parent | baf449fc5ff96f071bb0e3789fd3265f6d4fd9a0 (diff) | |
parent | 92c78a3bbcb2ce508b4bf1c4a1e0940406a024bb (diff) | |
download | u-boot-imx-cb5473205206c7f14cbb1e747f28ec75b48826e2.zip u-boot-imx-cb5473205206c7f14cbb1e747f28ec75b48826e2.tar.gz u-boot-imx-cb5473205206c7f14cbb1e747f28ec75b48826e2.tar.bz2 |
Merge branch 'fixes' into cleanups
Conflicts:
board/atmel/atngw100/atngw100.c
board/atmel/atstk1000/atstk1000.c
cpu/at32ap/at32ap700x/gpio.c
include/asm-avr32/arch-at32ap700x/clk.h
include/configs/atngw100.h
include/configs/atstk1002.h
include/configs/atstk1003.h
include/configs/atstk1004.h
include/configs/atstk1006.h
include/configs/favr-32-ezkit.h
include/configs/hammerhead.h
include/configs/mimc200.h
Diffstat (limited to 'cpu/mpc8xxx/ddr')
-rw-r--r-- | cpu/mpc8xxx/ddr/ctrl_regs.c | 80 | ||||
-rw-r--r-- | cpu/mpc8xxx/ddr/ddr.h | 17 | ||||
-rw-r--r-- | cpu/mpc8xxx/ddr/ddr1_2_dimm_params.h | 84 | ||||
-rw-r--r-- | cpu/mpc8xxx/ddr/main.c | 84 | ||||
-rw-r--r-- | cpu/mpc8xxx/ddr/options.c | 84 |
5 files changed, 219 insertions, 130 deletions
diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c index ca67551..1783e92 100644 --- a/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -95,16 +95,10 @@ static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr, col_bits_cs_n = dimm_params[i/2].n_col_addr - 8; } - /* FIXME: intlv_en, intlv_ctl only on CS0_CONFIG */ - if (i != 0) { - intlv_en = 0; - intlv_ctl = 0; - } - ddr->cs[i].config = (0 | ((cs_n_en & 0x1) << 31) | ((intlv_en & 0x3) << 29) - | ((intlv_en & 0xf) << 24) + | ((intlv_ctl & 0xf) << 24) | ((ap_n_en & 0x1) << 23) /* XXX: some implementation only have 1 bit starting at left */ @@ -117,6 +111,7 @@ static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr, | ((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) */ @@ -126,6 +121,7 @@ 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 */ @@ -196,6 +192,7 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, | ((ext_caslat & 0x1) << 12) | ((cntl_adj & 0x7) << 0) ); + debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3); } /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */ @@ -263,6 +260,7 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, | ((acttoact_mclk & 0x07) << 4) | ((wrtord_mclk & 0x07) << 0) ); + debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); } /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */ @@ -319,6 +317,7 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, | ((cke_pls & 0x7) << 6) | ((four_act & 0x1f) << 0) ); + debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); } /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */ @@ -385,6 +384,7 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, | ((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) */ @@ -449,6 +449,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, | ((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) */ @@ -461,6 +462,7 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr) | ((esdmode2 & 0xFFFF) << 16) | ((esdmode3 & 0xFFFF) << 0) ); + debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2); } /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */ @@ -480,6 +482,7 @@ static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, | ((refint & 0xFFFF) << 16) | ((bstopre & 0x3FFF) << 0) ); + debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval); } /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ @@ -520,7 +523,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, unsigned int wr; /* Write Recovery */ unsigned int dll_res; /* DLL Reset */ unsigned int mode; /* Normal=0 or Test=1 */ - unsigned int caslat; /* CAS# latency */ + unsigned int caslat = 0;/* CAS# latency */ /* BT: Burst Type (0=Sequential, 1=Interleaved) */ unsigned int bt; unsigned int bl; /* BL: Burst Length */ @@ -572,7 +575,9 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, 0x6, /* 2.5 clocks */ 0x3 /* 3.0 clocks */ }; - caslat = mode_caslat_table[cas_latency - 1]; + 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; @@ -611,6 +616,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, | ((esdmode & 0xFFFF) << 16) | ((sdmode & 0xFFFF) << 0) ); + debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); } @@ -673,6 +679,7 @@ static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr) | ((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) */ @@ -689,6 +696,7 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr) | ((wodt_on & 0xf) << 12) | ((wodt_off & 0xf) << 8) ); + debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5); } /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */ @@ -872,8 +880,13 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { phys_size_t sa = 0; phys_size_t ea = 0; - if (popts->ba_intlv_ctl && i > 0) { - /* Don't set up boundaries if bank interleaving */ + + if (popts->ba_intlv_ctl && (i > 0) && + ((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) { + /* Don't set up boundaries for other CS + * other than CS0, if bank interleaving + * is enabled and not CS2+CS3 interleaved. + */ break; } @@ -892,7 +905,9 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * on each controller is twice the amount present on * each controller. */ - ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1; + unsigned long long rank_density + = dimm_params[0].capacity; + ea = (2 * (rank_density >> dbw_cap_adj)) - 1; } else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { /* @@ -904,8 +919,44 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * controller needs to be programmed into its * respective CS0_BNDS. */ - sa = common_dimm->base_address; - ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1; + unsigned long long rank_density + = dimm_params[i/2].rank_density; + switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + /* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS + * needs to be set. + */ + sa = common_dimm->base_address; + ea = sa + (4 * (rank_density >> dbw_cap_adj))-1; + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + /* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS + * and CS2_CNDS need to be set. + */ + if (!(i&1)) { + sa = dimm_params[i/2].base_address; + ea = sa + (i * (rank_density >> + dbw_cap_adj)) - 1; + } + break; + case FSL_DDR_CS0_CS1: + /* CS0+CS1 interleaving, CS0_CNDS needs + * to be set + */ + sa = common_dimm->base_address; + ea = sa + (2 * (rank_density >> dbw_cap_adj))-1; + break; + case FSL_DDR_CS2_CS3: + /* CS2+CS3 interleaving*/ + if (i == 2) { + sa = dimm_params[i/2].base_address; + ea = sa + (2 * (rank_density >> + dbw_cap_adj)) - 1; + } + break; + default: /* No bank(chip-select) interleaving */ + break; + } } else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { /* @@ -953,6 +1004,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, | ((ea & 0xFFF) << 0) /* ending address MSB */ ); + debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds); set_csn_config(i, ddr, popts, dimm_params); set_csn_config_2(i, ddr); } diff --git a/cpu/mpc8xxx/ddr/ddr.h b/cpu/mpc8xxx/ddr/ddr.h index f5dc40a..9ffd548 100644 --- a/cpu/mpc8xxx/ddr/ddr.h +++ b/cpu/mpc8xxx/ddr/ddr.h @@ -10,8 +10,8 @@ #define FSL_DDR_MAIN_H #include <asm/fsl_ddr_sdram.h> +#include <asm/fsl_ddr_dimm_params.h> -#include "ddr1_2_dimm_params.h" #include "common_timing_params.h" /* @@ -31,17 +31,17 @@ compute_dimm_parameters(const generic_spd_eeprom_t *spd, * * All data structures have to be on the stack */ -#define CFG_NUM_DDR_CTLRS CONFIG_NUM_DDR_CONTROLLERS -#define CFG_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR +#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[CFG_NUM_DDR_CTLRS][CFG_DIMM_SLOTS_PER_CTLR]; + spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR]; struct dimm_params_s - dimm_params[CFG_NUM_DDR_CTLRS][CFG_DIMM_SLOTS_PER_CTLR]; - memctl_options_t memctl_opts[CFG_NUM_DDR_CTLRS]; - common_timing_params_t common_timing_params[CFG_NUM_DDR_CTLRS]; - fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CFG_NUM_DDR_CTLRS]; + 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 */ @@ -71,6 +71,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, unsigned int number_of_dimms); extern unsigned int populate_memctl_options(int all_DIMMs_registered, memctl_options_t *popts, + dimm_params_t *pdimm, unsigned int ctrl_num); extern unsigned int mclk_to_picos(unsigned int mclk); diff --git a/cpu/mpc8xxx/ddr/ddr1_2_dimm_params.h b/cpu/mpc8xxx/ddr/ddr1_2_dimm_params.h deleted file mode 100644 index c794eed..0000000 --- a/cpu/mpc8xxx/ddr/ddr1_2_dimm_params.h +++ /dev/null @@ -1,84 +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 - -/* 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; - - /* 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; - - /* DIMM timing parameters */ - - /* - * 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 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 */ -} 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/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c index ac4b80c..f1ad132 100644 --- a/cpu/mpc8xxx/ddr/main.c +++ b/cpu/mpc8xxx/ddr/main.c @@ -44,10 +44,10 @@ extern void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, * * 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 + * 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 @@ -55,24 +55,24 @@ extern void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, * CS0_CONFIG[INTLV_CTL] of each memory controller. * * memory controller documentation | number of chip selects - * | per memory controller supported + * | 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 + * 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 + * Name of field | documentation name | this code * -----------------------------|-----------------------|------------------ - * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving - * | interleaving + * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving + * | interleaving */ #ifdef DEBUG @@ -164,6 +164,24 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo, } if (j == 2) { *memctl_interleaving = 1; + + printf("\nMemory controller interleaving enabled: "); + + switch (pinfo->memctl_opts[0].memctl_interleaving_mode) { + case FSL_DDR_CACHE_LINE_INTERLEAVING: + printf("Cache-line interleaving!\n"); + break; + case FSL_DDR_PAGE_INTERLEAVING: + printf("Page interleaving!\n"); + break; + case FSL_DDR_BANK_INTERLEAVING: + printf("Bank interleaving!\n"); + break; + case FSL_DDR_SUPERBANK_INTERLEAVING: + printf("Super bank interleaving\n"); + default: + break; + } } /* Check that all controllers are rank interleaving. */ @@ -175,10 +193,30 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo, } if (j == 2) { *rank_interleaving = 1; + + printf("Bank(chip-select) interleaving enabled: "); + + switch (pinfo->memctl_opts[0].ba_intlv_ctl & + FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + printf("CS0+CS1+CS2+CS3\n"); + break; + case FSL_DDR_CS0_CS1: + printf("CS0+CS1\n"); + break; + case FSL_DDR_CS2_CS3: + printf("CS2+CS3\n"); + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + printf("CS0+CS1 and CS2+CS3\n"); + default: + break; + } } if (*memctl_interleaving) { phys_addr_t addr; + phys_size_t total_mem_per_ctlr = 0; /* * If interleaving between memory controllers, @@ -197,14 +235,18 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo, for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { addr = 0; + pinfo->common_timing_params[i].base_address = + (phys_addr_t)addr; for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { unsigned long long cap = pinfo->dimm_params[i][j].capacity; pinfo->dimm_params[i][j].base_address = addr; addr += (phys_addr_t)(cap >> dbw_cap_adj[i]); + total_mem_per_ctlr += cap >> dbw_cap_adj[i]; } } + pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr; } else { /* * Simple linear assignment if memory @@ -270,7 +312,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step) generic_spd_eeprom_t *spd = &(pinfo->spd_installed_dimms[i][j]); dimm_params_t *pdimm = - &(pinfo->dimm_params[i][j]); + &(pinfo->dimm_params[i][j]); retval = compute_dimm_parameters(spd, pdimm, i); if (retval == 2) { @@ -314,7 +356,8 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step) */ populate_memctl_options( timing_params[i].all_DIMMs_registered, - &pinfo->memctl_opts[i], i); + &pinfo->memctl_opts[i], + pinfo->dimm_params[i], i); } case STEP_ASSIGN_ADDRESSES: @@ -432,9 +475,14 @@ phys_size_t fsl_ddr_sdram(void) */ memctl_interleaved = 1; } else { - printf("Error: memctl interleaving not " + printf("Warning: memctl interleaving not " "properly configured on all controllers\n"); - while (1); + memctl_interleaved = 0; + for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) + info.memctl_opts[i].memctl_interleaving = 0; + debug("Recomputing with memctl_interleaving off.\n"); + total_memory = fsl_ddr_compute(&info, + STEP_ASSIGN_ADDRESSES); } } diff --git a/cpu/mpc8xxx/ddr/options.c b/cpu/mpc8xxx/ddr/options.c index 6c2b43c..af7f73a 100644 --- a/cpu/mpc8xxx/ddr/options.c +++ b/cpu/mpc8xxx/ddr/options.c @@ -13,13 +13,16 @@ /* 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); unsigned int populate_memctl_options(int all_DIMMs_registered, memctl_options_t *popts, + dimm_params_t *pdimm, unsigned int ctrl_num) { unsigned int i; + const char *p; /* Chip select options. */ @@ -179,19 +182,88 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, #error "FIXME determine four activates for DDR3" #endif - /* ODT should only be used for DDR2 */ - - /* FIXME? */ - /* - * Interleaving checks. + * 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 the 2 memory * controllers. + * + * XXX: Attempt to set both 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 ((p = getenv("memctl_intlv_ctl")) != NULL) { + if (pdimm[0].n_ranks == 0) { + printf("There is no rank on CS0. Because only rank on " + "CS0 and ranks chip-select interleaved with CS0" + " are controller interleaved, force non memory " + "controller interleaving\n"); + popts->memctl_interleaving = 0; + } else { + popts->memctl_interleaving = 1; + if (strcmp(p, "cacheline") == 0) + popts->memctl_interleaving_mode = + FSL_DDR_CACHE_LINE_INTERLEAVING; + else if (strcmp(p, "page") == 0) + popts->memctl_interleaving_mode = + FSL_DDR_PAGE_INTERLEAVING; + else if (strcmp(p, "bank") == 0) + popts->memctl_interleaving_mode = + FSL_DDR_BANK_INTERLEAVING; + else if (strcmp(p, "superbank") == 0) + popts->memctl_interleaving_mode = + FSL_DDR_SUPERBANK_INTERLEAVING; + else + popts->memctl_interleaving_mode = + simple_strtoul(p, NULL, 0); + } + } + + if( (p = getenv("ba_intlv_ctl")) != NULL) { + if (strcmp(p, "cs0_cs1") == 0) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1; + else if (strcmp(p, "cs2_cs3") == 0) + popts->ba_intlv_ctl = FSL_DDR_CS2_CS3; + else if (strcmp(p, "cs0_cs1_and_cs2_cs3") == 0) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3; + else if (strcmp(p, "cs0_cs1_cs2_cs3") == 0) + popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3; + else + popts->ba_intlv_ctl = simple_strtoul(p, NULL, 0); + + switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { + case FSL_DDR_CS0_CS1_CS2_CS3: + 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, force non-interleaving!\n"); + } + break; + case FSL_DDR_CS2_CS3: + if (pdimm[1].n_ranks !=2){ + popts->ba_intlv_ctl = 0; + printf("Not enough bank(CS) for CS2+CS3, " + "force non-interleaving!\n"); + } + break; + case FSL_DDR_CS0_CS1_AND_CS2_CS3: + if ((pdimm[0].n_ranks != 2)||(pdimm[1].n_ranks != 2)) { + popts->ba_intlv_ctl = 0; + printf("Not enough bank(CS) for CS0+CS1 or " + "CS2+CS3, force non-interleaving!\n"); + } + break; + default: + popts->ba_intlv_ctl = 0; + break; + } + } - fsl_ddr_board_options(popts, ctrl_num); + fsl_ddr_board_options(popts, pdimm, ctrl_num); return 0; } |