Skip to contentSkip to conversation

Make DDR interleaving mode work correctly

PATCH New Haiying Wang 5 participants 6 messages Oct 3, 2008 – Oct 13, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

Fix some bugs:
1. Correctly set intlv_ctl in cs_config.
2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.

---
 cpu/mpc8xxx/ddr/ctrl_regs.c     |   61 +++++++++++++++++++++++++++++++-------
 cpu/mpc8xxx/ddr/main.c          |    5 +++
 include/asm-ppc/fsl_ddr_sdram.h |   12 +++++++
 3 files changed, 66 insertions(+), 12 deletions(-)
cpu/mpc8xxx/ddr/ctrl_regs.c +49 -12
index e6c2a5c..6297141 100644
@@ -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@left */
@@ -874,8 +868,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;
 		}
 
@@ -894,7 +893,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) {
 			/*
@@ -906,8 +907,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) {
 			/*
cpu/mpc8xxx/ddr/main.c +5 -0
index c340d56..d26c5c5 100644
@@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
 
 	if (*memctl_interleaving) {
 		phys_addr_t addr;
+		phys_size_t total_mem_per_ctlr = 0;
 
 		/*
 		 * If interleaving between memory controllers,
@@ -197,14 +198,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
include/asm-ppc/fsl_ddr_sdram.h +12 -0
index 8adde34..c1ea7cd 100644
@@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
 typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #endif
 
+/* 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
+
 /* Record of register values computed */
 typedef struct fsl_ddr_cfg_regs_s {
 	struct {
Signature · 1 line
1.6.0.2
#1 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.

Quoted 171 lines · Haiying Wang

Fix some bugs:
1. Correctly set intlv_ctl in cs_config.
2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.

---
 cpu/mpc8xxx/ddr/ctrl_regs.c     |   61 +++++++++++++++++++++++++++++++-------
 cpu/mpc8xxx/ddr/main.c          |    5 +++
 include/asm-ppc/fsl_ddr_sdram.h |   12 +++++++
 3 files changed, 66 insertions(+), 12 deletions(-)
cpu/mpc8xxx/ddr/ctrl_regs.c +49 -12
index e6c2a5c..6297141 100644
@@ -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 */
@@ -874,8 +868,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;
               }
 
@@ -894,7 +893,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) {
                       /*
@@ -906,8 +907,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) {
                       /*
cpu/mpc8xxx/ddr/main.c +5 -0
index c340d56..d26c5c5 100644
@@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
 
       if (*memctl_interleaving) {
               phys_addr_t addr;
+               phys_size_t total_mem_per_ctlr = 0;
 
               /*
                * If interleaving between memory controllers,
@@ -197,14 +198,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
include/asm-ppc/fsl_ddr_sdram.h +12 -1
index 8adde34..c1ea7cd 100644
@@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
 typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #endif
 
+/* 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
+
 /* Record of register values computed */
 typedef struct fsl_ddr_cfg_regs_s {
       struct {
--

1.6.0.2

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

#2 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

Quoted 11 lines · Andy Fleming

If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.

Quoted 7 lines · Haiying Wang

Fix some bugs:
1. Correctly set intlv_ctl in cs_config.
2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.

Sounds good by me.

ACK.

jdl

#3 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

In reply to Andy Fleming
Quoted 2 lines · Andy Fleming

If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.

The code doesn't impact 83xx and thus not sure why you need Kim's ack.

- k

Quoted 10 lines
Quoted 7 lines · Haiying Wang

Fix some bugs:
1. Correctly set intlv_ctl in cs_config.
2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
3. Set base_address and total memory for each ddr controller in memory
controller interleaving mode.

#4 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

Quoted 7 lines · On Wed, 8 Oct 2008 00:39:38 -0500 Kumar Gala <[email protected]> wrote:
Quoted 2 lines · Andy Fleming

If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.

The code doesn't impact 83xx and thus not sure why you need Kim's ack.

ack

on Kumar's comment, that is :)

Kim

#5 lore raw

PATCH 1/6 Make DDR interleaving mode work correctly

In reply to Haiying Wang
Quoted 7 lines · Haiying Wang

Fix some bugs:
1. Correctly set intlv_ctl in cs_config.
2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.

Applied 1-6 to 85xx-next with some modifications from Kumar, thanks