summaryrefslogtreecommitdiff
path: root/cpu/mpc8xxx/ddr/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/mpc8xxx/ddr/main.c')
-rw-r--r--cpu/mpc8xxx/ddr/main.c84
1 files changed, 66 insertions, 18 deletions
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);
}
}