[U-Boot] [PATCH 3/6] Check DDR interleaving mode

Haiying Wang Haiying.Wang at freescale.com
Fri Oct 3 18:37:10 CEST 2008


* Check DDR interleaving mode from environment by reading memctl_intlv_ctl and
ba_intlv_ctl.
* Print DDR interleaving mode information
* Add doc/README.fsl-ddr to describe the interleaving setting

Signed-off-by: Haiying Wang <Haiying.Wang at freescale.com>
---
 cpu/mpc8xxx/ddr/main.c    |   37 +++++++++++++++++++++
 cpu/mpc8xxx/ddr/options.c |   80 ++++++++++++++++++++++++++++++++++++++++++---
 doc/README.fsl-ddr        |   69 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 181 insertions(+), 5 deletions(-)
 create mode 100644 doc/README.fsl-ddr

diff --git a/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c
index 98a8651..d5173c3 100644
--- a/cpu/mpc8xxx/ddr/main.c
+++ b/cpu/mpc8xxx/ddr/main.c
@@ -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,6 +193,25 @@ 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) {
diff --git a/cpu/mpc8xxx/ddr/options.c b/cpu/mpc8xxx/ddr/options.c
index 99b5685..714e88d 100644
--- a/cpu/mpc8xxx/ddr/options.c
+++ b/cpu/mpc8xxx/ddr/options.c
@@ -22,6 +22,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 			unsigned int ctrl_num)
 {
 	unsigned int i;
+	const char *p;
 
 	/* Chip select options. */
 
@@ -181,17 +182,86 @@ 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("No 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("No 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("No 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, pdimm, ctrl_num);
 
diff --git a/doc/README.fsl-ddr b/doc/README.fsl-ddr
new file mode 100644
index 0000000..357ec05
--- /dev/null
+++ b/doc/README.fsl-ddr
@@ -0,0 +1,69 @@
+
+Table of interleaving modes supported in cpu/8xxx/ddr/
+======================================================
+  +-------------+---------------------------------------------------------+
+  |             |                   Rank Interleaving                     |
+  |             +--------+-----------+-----------+------------+-----------+
+  |Memory       |        |           |           |    2x2     |    4x1    |
+  |Controller   |  None  | 2x1 lower | 2x1 upper | {CS0+CS1}, | {CS0+CS1+ |
+  |Interleaving |        | {CS0+CS1} | {CS2+CS3} | {CS2+CS3}  |  CS2+CS3} |
+  +-------------+--------+-----------+-----------+------------+-----------+
+  |None         |  Yes   | Yes       | Yes       | Yes        | Yes       |
+  +-------------+--------+-----------+-----------+------------+-----------+
+  |Cacheline    |  Yes   | Yes       | No        | No, Only(*)| Yes       |
+  |             |CS0 Only|           |           | {CS0+CS1}  |           |
+  +-------------+--------+-----------+-----------+------------+-----------+
+  |Page         |  Yes   | Yes       | No        | No, Only(*)| Yes       |
+  |             |CS0 Only|           |           | {CS0+CS1}  |           |
+  +-------------+--------+-----------+-----------+------------+-----------+
+  |Bank         |  Yes   | Yes       | No        | No, Only(*)| Yes       |
+  |             |CS0 Only|           |           | {CS0+CS1}  |           |
+  +-------------+--------+-----------+-----------+------------+-----------+
+  |Superbank    |  No    | Yes       | No        | No, Only(*)| Yes       |
+  |             |        |           |           | {CS0+CS1}  |           |
+  +-------------+--------+-----------+-----------+------------+-----------+
+ (*) Although the hardware can be configured with memory controller
+ interleaving using "2x2" rank interleaving, it only interleaves {CS0+CS1}
+ from each controller. {CS2+CS3} on each controller are only rank
+ interleaved on that controller.
+
+The ways to configure the ddr interleaving mode
+==============================================
+1. In board header file(e.g.MPC8572DS.h), add default interleaving setting
+   under "CONFIG_EXTRA_ENV_SETTINGS", like:
+	#define CONFIG_EXTRA_ENV_SETTINGS				\
+	 "memctl_intlv_ctl=2\0"						\
+	 ......
+
+2. Run u-boot "setenv" command to configure the memory interleaving mode.
+   Either numerical or string value is accepted.
+
+  # disable memory controller interleaving
+  setenv memctl_intlv_ctl
+
+  # cacheline interleaving
+  setenv memctl_intlv_ctl 0 or setenv memctl_intlv_ctl cacheline
+
+  # page interleaving
+  setenv memctl_intlv_ctl 1 or setenv memctl_intlv_ctl page
+
+  # bank interleaving
+  setenv memctl_intlv_ctl 2 or setenv memctl_intlv_ctl bank
+
+  # superbank
+  setenv memctl_intlv_ctl 3 or setenv memctl_intlv_ctl superbank
+
+  # disable bank (chip-select) interleaving
+  setenv ba_intlv_ctl
+
+  # bank(chip-select) interleaving cs0+cs1
+  setenv ba_intlv_ctl 0x40 or setenv ba_intlv_ctl cs0_cs1
+
+  # bank(chip-select) interleaving cs2+cs3
+  setenv ba_intlv_ctl 0x20 or setenv ba_intlv_ctl cs2_cs3
+
+  # bank(chip-select) interleaving (cs0+cs1) and (cs2+cs3)  (2x2)
+  setenv ba_intlv_ctl 0x60 or setenv ba_intlv_ctl cs0_cs1_and_cs2_cs3
+
+  # bank(chip-select) interleaving (cs0+cs1+cs2+cs3) (4x1)
+  setenv ba_intlv_ctl 0x04 or setenv ba_intlv_ctl cs0_cs1_cs2_cs3
+
-- 
1.6.0.2



More information about the U-Boot mailing list