Commit a4c66509 authored by York Sun's avatar York Sun Committed by Andy Fleming

powerpc/mpc8xxx: Enable 3-way and 4-way DDR interleaving

Restructure DDR interleaving option to support 3 and 4 DDR controllers
for 2-, 3- and 4-way interleaving.
Signed-off-by: default avatarYork Sun <yorksun@freescale.com>
Signed-off-by: default avatarAndy Fleming <afleming@freescale.com>
parent fcea3068
......@@ -430,10 +430,20 @@ static void dump_spd_ddr_reg(void)
case 0:
ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
break;
#ifdef CONFIG_SYS_MPC85xx_DDR2_ADDR
#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
case 1:
ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
break;
#endif
#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
case 2:
ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
break;
#endif
#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
case 3:
ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
break;
#endif
default:
printf("%s unexpected controller number = %u\n",
......
......@@ -32,9 +32,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
case 0:
ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
break;
#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
case 1:
ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
break;
#endif
#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
case 2:
ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
break;
#endif
#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
case 3:
ddr = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
break;
#endif
default:
printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
return;
......
......@@ -151,8 +151,19 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
if (dimm_params[dimm_number].n_ranks > 0) {
go_config = 1;
/* These fields only available in CS0_CONFIG */
intlv_en = popts->memctl_interleaving;
intlv_ctl = popts->memctl_interleaving_mode;
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:
......@@ -1413,73 +1424,37 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
/* Chip Select Memory Bounds (CSn_BNDS) */
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
unsigned long long ea = 0, sa = 0;
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;
= dimm_params[dimm_number].rank_density >> dbw_cap_adj;
if (((i == 1) && (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1)) ||
((i == 2) && (popts->ba_intlv_ctl & 0x04)) ||
((i == 3) && (popts->ba_intlv_ctl & FSL_DDR_CS2_CS3))) {
/*
* Don't set up boundaries for unused CS
* cs1 for cs0_cs1, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3
* cs2 for cs0_cs1_cs2_cs3
* cs3 for cs2_cs3, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3
* But we need to set the ODT_RD_CFG and
* ODT_WR_CFG for CS1_CONFIG here.
*/
set_csn_config(dimm_number, i, ddr, popts, dimm_params);
continue;
}
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 && popts->ba_intlv_ctl) {
/*
* This works superbank 2CS
* There are 2 or more memory controllers configured
* identically, memory is interleaved between them,
* and each controller uses rank interleaving within
* itself. Therefore the starting and ending address
* on each controller is twice the amount present on
* each controller. If any CS is not included in the
* interleaving, the memory on that CS is not accssible
* and the total memory size is reduced. The CS is also
* disabled.
*/
unsigned long long ctlr_density = 0;
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:
ctlr_density = dimm_params[0].rank_density * 2;
if (i > 1)
cs_en = 0;
break;
case FSL_DDR_CS2_CS3:
ctlr_density = dimm_params[0].rank_density;
default:
if (i > 0)
cs_en = 0;
break;
case FSL_DDR_CS0_CS1_CS2_CS3:
/*
* The four CS interleaving should have been verified by
* populate_memctl_options()
*/
ctlr_density = dimm_params[0].rank_density * 4;
break;
default:
break;
}
ea = (CONFIG_NUM_DDR_CONTROLLERS *
(ctlr_density >> dbw_cap_adj)) - 1;
}
else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {
sa = common_dimm->base_address;
ea = common_dimm->total_mem - 1;
} else if (!popts->memctl_interleaving) {
/*
* If memory interleaving between controllers is NOT
* enabled, the starting address for each memory
......@@ -1491,49 +1466,40 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
*/
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;
ea = common_dimm->total_mem - 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 == 2) && (dimm_number == 0)) {
if ((i >= 2) && (dimm_number == 0)) {
sa = dimm_params[dimm_number].base_address +
2 * (rank_density >> dbw_cap_adj);
ea = sa + 2 * (rank_density >> dbw_cap_adj) - 1;
2 * rank_density;
ea = sa + 2 * rank_density - 1;
} else {
sa = dimm_params[dimm_number].base_address;
ea = sa + (2 * (rank_density >>
dbw_cap_adj)) - 1;
ea = sa + 2 * rank_density - 1;
}
break;
case FSL_DDR_CS0_CS1:
/* CS0+CS1 interleaving, CS0_CNDS needs
* to be set
*/
if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
sa = dimm_params[dimm_number].base_address;
ea = sa + (rank_density >> dbw_cap_adj) - 1;
sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
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 >> dbw_cap_adj);
ea += rank_density;
break;
case FSL_DDR_CS2_CS3:
/* CS2+CS3 interleaving*/
if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
sa = dimm_params[dimm_number].base_address;
ea = sa + (rank_density >> dbw_cap_adj) - 1;
sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
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;
......@@ -1542,38 +1508,18 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
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;
}
}
else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {
/*
* Only the rank on CS0 of each memory controller may
* be used if memory controller interleaving is used
* without rank interleaving within each memory
* controller. However, the ending address programmed
* into each CS0 must be the sum of the amount of
* memory in the two CS0 ranks.
*/
if (i == 0) {
ea = (2 * (rank_density >> dbw_cap_adj)) - 1;
}
}
else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) {
/*
* No rank interleaving and no memory controller
* interleaving.
*/
sa = dimm_params[dimm_number].base_address;
ea = sa + (rank_density >> dbw_cap_adj) - 1;
if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
} else {
sa = 0;
ea = 0;
}
}
sa >>= 24;
ea >>= 24;
......
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2008-2011 Freescale Semiconductor, Inc.
* 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
......@@ -79,7 +79,7 @@ unsigned int mclk_to_picos(unsigned int mclk)
void
__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
unsigned int memctl_interleaved,
unsigned int law_memctl,
unsigned int ctrl_num)
{
unsigned long long base = memctl_common_params->base_address;
......@@ -98,28 +98,13 @@ __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
if ((base + size) >= CONFIG_MAX_MEM_MAPPED)
size = CONFIG_MAX_MEM_MAPPED - base;
#endif
if (ctrl_num == 0) {
/*
* Set up LAW for DDR controller 1 space.
*/
unsigned int lawbar1_target_id = memctl_interleaved
? LAW_TRGT_IF_DDR_INTRLV : LAW_TRGT_IF_DDR_1;
if (set_ddr_laws(base, size, lawbar1_target_id) < 0) {
printf("%s: ERROR (ctrl #0, intrlv=%d)\n", __func__,
memctl_interleaved);
return ;
}
} else if (ctrl_num == 1) {
if (set_ddr_laws(base, size, LAW_TRGT_IF_DDR_2) < 0) {
printf("%s: ERROR (ctrl #1)\n", __func__);
return ;
}
} else {
printf("%s: unexpected DDR controller number (%u)\n", __func__,
ctrl_num);
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
......@@ -127,6 +112,15 @@ 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
}
void board_add_ram_info(int use_default)
{
#if defined(CONFIG_MPC83xx)
......@@ -137,6 +131,9 @@ void board_add_ram_info(int use_default)
#elif defined(CONFIG_MPC86xx)
ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR);
#endif
#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
......@@ -180,7 +177,29 @@ void board_add_ram_info(int use_default)
else
puts(", ECC off)");
#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
#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: ");
......
......@@ -76,6 +76,13 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
#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
/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
*/
......
......@@ -60,8 +60,12 @@ enum law_trgt_if {
LAW_TRGT_IF_DDR_1 = 0x10,
LAW_TRGT_IF_DDR_2 = 0x11, /* 2nd controller */
LAW_TRGT_IF_DDR_3 = 0x12,
LAW_TRGT_IF_DDR_4 = 0x13,
LAW_TRGT_IF_DDR_INTRLV = 0x14,
LAW_TRGT_IF_DDR_INTLV_34 = 0x15,
LAW_TRGT_IF_DDR_INTLV_123 = 0x17,
LAW_TRGT_IF_DDR_INTLV_1234 = 0x16,
LAW_TRGT_IF_BMAN = 0x18,
LAW_TRGT_IF_DCSR = 0x1d,
LAW_TRGT_IF_LBC = 0x1f,
......@@ -87,6 +91,12 @@ enum law_trgt_if {
LAW_TRGT_IF_DPAA_SWP_SRAM = 0x0e,
LAW_TRGT_IF_DDR = 0x0f,
LAW_TRGT_IF_DDR_2 = 0x16, /* 2nd controller */
/* place holder for 3-way and 4-way interleaving */
LAW_TRGT_IF_DDR_3,
LAW_TRGT_IF_DDR_4,
LAW_TRGT_IF_DDR_INTLV_34,
LAW_TRGT_IF_DDR_INTLV_123,
LAW_TRGT_IF_DDR_INTLV_1234,
};
#define LAW_TRGT_IF_DDR_1 LAW_TRGT_IF_DDR
#define LAW_TRGT_IF_PCI_1 LAW_TRGT_IF_PCI
......
......@@ -2621,6 +2621,7 @@ struct ccsr_rman {
#define CONFIG_SYS_FSL_CORENET_CCM_OFFSET 0x0000
#define CONFIG_SYS_MPC85xx_DDR_OFFSET 0x8000
#define CONFIG_SYS_MPC85xx_DDR2_OFFSET 0x9000
#define CONFIG_SYS_MPC85xx_DDR3_OFFSET 0xA000
#define CONFIG_SYS_FSL_CORENET_CLK_OFFSET 0xE1000
#define CONFIG_SYS_FSL_CORENET_RCPM_OFFSET 0xE2000
#define CONFIG_SYS_FSL_CORENET_SERDES_OFFSET 0xEA000
......@@ -2740,6 +2741,8 @@ struct ccsr_rman {
(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR_OFFSET)
#define CONFIG_SYS_MPC85xx_DDR2_ADDR \
(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR2_OFFSET)
#define CONFIG_SYS_MPC85xx_DDR3_ADDR \
(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR3_OFFSET)
#define CONFIG_SYS_LBC_ADDR \
(CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET)
#define CONFIG_SYS_IFC_ADDR \
......
Table of interleaving modes supported in cpu/8xxx/ddr/
Table of interleaving 2-4 controllers
=====================================
+--------------+-----------------------------------------------------------+
|Configuration | Memory Controller |
| | 1 2 3 4 |
|--------------+--------------+--------------+-----------------------------+
| Two memory | Not Intlv'ed | Not Intlv'ed | |
| complexes +--------------+--------------+ |
| | 2-way Intlv'ed | |
|--------------+--------------+--------------+--------------+ |
| | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | |
| Three memory +--------------+--------------+--------------+ |
| complexes | 2-way Intlv'ed | Not Intlv'ed | |
| +-----------------------------+--------------+ |
| | 3-way Intlv'ed | |
+--------------+--------------+--------------+--------------+--------------+
| | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed |
| Four memory +--------------+--------------+--------------+--------------+
| complexes | 2-way Intlv'ed | 2-way Intlv'ed |
| +-----------------------------+-----------------------------+
| | 4-way Intlv'ed |
+--------------+-----------------------------------------------------------+
Table of 2-way interleaving modes supported in cpu/8xxx/ddr/
======================================================
+-------------+---------------------------------------------------------+
| | Rank Interleaving |
......@@ -56,6 +79,15 @@ The ways to configure the ddr interleaving mode
# superbank
setenv hwconfig "fsl_ddr:ctlr_intlv=superbank"
# 1KB 3-way interleaving
setenv hwconfig "fsl_ddr:ctlr_intlv=3way_1KB"
# 4KB 3-way interleaving
setenv hwconfig "fsl_ddr:ctlr_intlv=3way_4KB"
# 8KB 3-way interleaving
setenv hwconfig "fsl_ddr:ctlr_intlv=3way_8KB"
# disable bank (chip-select) interleaving
setenv hwconfig "fsl_ddr:bank_intlv=null"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment