public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3
@ 2008-08-20 23:22 Kumar Gala
  2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
  2008-08-26 23:07 ` [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Wolfgang Denk
  0 siblings, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: James Yang <James.Yang@freescale.com>

Also added a few helper functions for DDR1 & DDR2 to print SPD info and
verify the checksum.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 common/Makefile   |    1 +
 common/ddr_spd.c  |  519 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/ddr_spd.h |  292 ++++++++++++++++++++++++++++++
 3 files changed, 812 insertions(+), 0 deletions(-)
 create mode 100644 common/ddr_spd.c
 create mode 100644 include/ddr_spd.h

diff --git a/common/Makefile b/common/Makefile
index dd139d6..8048341 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -150,6 +150,7 @@ COBJS-y += cmd_mac.o
 COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
 COBJS-$(CONFIG_MP) += cmd_mp.o
 COBJS-$(CONFIG_CMD_SF) += cmd_sf.o
+COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(AOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/common/ddr_spd.c b/common/ddr_spd.c
new file mode 100644
index 0000000..03cbe1d
--- /dev/null
+++ b/common/ddr_spd.c
@@ -0,0 +1,519 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <ddr_spd.h>
+
+void
+ddr1_spd_dump(const ddr1_spd_eeprom_t *spd)
+{
+	unsigned int i;
+
+	printf("%-3d    : %02x %s\n",
+	       0, spd->info_size,
+	       " spd->info_size,   *  0 # bytes written into serial memory *");
+	printf("%-3d    : %02x %s\n",
+	       1, spd->chip_size,
+	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
+	printf("%-3d    : %02x %s\n",
+	       2, spd->mem_type,
+	       " spd->mem_type,    *  2 Fundamental memory type *");
+	printf("%-3d    : %02x %s\n",
+	       3, spd->nrow_addr,
+	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       4, spd->ncol_addr,
+	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       5, spd->nrows,
+	       " spd->nrows        *  5 # of DIMM Banks *");
+	printf("%-3d    : %02x %s\n",
+	       6, spd->dataw_lsb,
+	       " spd->dataw_lsb,   *  6 Data Width lsb of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       7, spd->dataw_msb,
+	       " spd->dataw_msb,   *  7 Data Width msb of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       8, spd->voltage,
+	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       9, spd->clk_cycle,
+	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       10, spd->clk_access,
+	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       11, spd->config,
+	       " spd->config,      * 11 DIMM Configuration type *");
+	printf("%-3d    : %02x %s\n",
+	       12, spd->refresh,
+	       " spd->refresh,     * 12 Refresh Rate/Type *");
+	printf("%-3d    : %02x %s\n",
+	       13, spd->primw,
+	       " spd->primw,       * 13 Primary SDRAM Width *");
+	printf("%-3d    : %02x %s\n",
+	       14, spd->ecw,
+	       " spd->ecw,         * 14 Error Checking SDRAM width *");
+	printf("%-3d    : %02x %s\n",
+	       15, spd->min_delay,
+	       " spd->min_delay,   * 15 Back to Back Random Access *");
+	printf("%-3d    : %02x %s\n",
+	       16, spd->burstl,
+	       " spd->burstl,      * 16 Burst Lengths Supported *");
+	printf("%-3d    : %02x %s\n",
+	       17, spd->nbanks,
+	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
+	printf("%-3d    : %02x %s\n",
+	       18, spd->cas_lat,
+	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
+	printf("%-3d    : %02x %s\n",
+	       19, spd->cs_lat,
+	       " spd->cs_lat,      * 19 Chip Select Latency *");
+	printf("%-3d    : %02x %s\n",
+	       20, spd->write_lat,
+	       " spd->write_lat,   * 20 Write Latency/Recovery *");
+	printf("%-3d    : %02x %s\n",
+	       21, spd->mod_attr,
+	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       22, spd->dev_attr,
+	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       23, spd->clk_cycle2,
+	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       24, spd->clk_access2,
+	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       25, spd->clk_cycle3,
+	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       26, spd->clk_access3,
+	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       27, spd->trp,
+	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
+	printf("%-3d    : %02x %s\n",
+	       28, spd->trrd,
+	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
+	printf("%-3d    : %02x %s\n",
+	       29, spd->trcd,
+	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
+	printf("%-3d    : %02x %s\n",
+	       30, spd->tras,
+	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
+	printf("%-3d    : %02x %s\n",
+	       31, spd->bank_dens,
+	       " spd->bank_dens,   * 31 Density of each bank on module *");
+	printf("%-3d    : %02x %s\n",
+	       32, spd->ca_setup,
+	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       33, spd->ca_hold,
+	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       34, spd->data_setup,
+	       " spd->data_setup,  * 34 Data signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       35, spd->data_hold,
+	       " spd->data_hold,   * 35 Data signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       36, spd->res_36_40[0],
+	       " spd->res_36_40[0], * 36 Reserved / tWR *");
+	printf("%-3d    : %02x %s\n",
+	       37, spd->res_36_40[1],
+	       " spd->res_36_40[1], * 37 Reserved / tWTR *");
+	printf("%-3d    : %02x %s\n",
+	       38, spd->res_36_40[2],
+	       " spd->res_36_40[2], * 38 Reserved / tRTP *");
+	printf("%-3d    : %02x %s\n",
+	       39, spd->res_36_40[3],
+	       " spd->res_36_40[3], * 39 Reserved / mem_probe *");
+	printf("%-3d    : %02x %s\n",
+	       40, spd->res_36_40[4],
+	       " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *");
+	printf("%-3d    : %02x %s\n",
+	       41, spd->trc,
+	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
+	printf("%-3d    : %02x %s\n",
+	       42, spd->trfc,
+	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
+	printf("%-3d    : %02x %s\n",
+	       43, spd->tckmax,
+	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
+	printf("%-3d    : %02x %s\n",
+	       44, spd->tdqsq,
+	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
+	printf("%-3d    : %02x %s\n",
+	       45, spd->tqhs,
+	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
+	printf("%-3d    : %02x %s\n",
+	       46, spd->res_46,
+	       " spd->res_46,  * 46 Reserved/ PLL Relock time *");
+	printf("%-3d    : %02x %s\n",
+	       47, spd->dimm_height,
+	       " spd->dimm_height  * 47 SDRAM DIMM Height *");
+
+	printf("%-3d-%3d: ",  48, 61);
+	for (i = 0; i < 14; i++) {
+		printf("%02x", spd->res_48_61[i]);
+	}
+	printf(" * 48-61 IDD in SPD and Reserved space *\n");
+
+	printf("%-3d    : %02x %s\n",
+	       62, spd->spd_rev,
+	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
+	printf("%-3d    : %02x %s\n",
+	       63, spd->cksum,
+	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
+	printf("%-3d-%3d: ",  64, 71);
+
+	for (i = 0; i < 8; i++) {
+		printf("%02x", spd->mid[i]);
+	}
+
+	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+	printf("%-3d    : %02x %s\n",
+	       72, spd->mloc,
+	       " spd->mloc,        * 72 Manufacturing Location *");
+
+	printf("%-3d-%3d: >>",  73, 90);
+	for (i = 0; i < 18; i++) {
+		printf("%c", spd->mpart[i]);
+	}
+
+	printf("<<* 73 Manufacturer's Part Number *\n");
+
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       91, 92, spd->rev[0], spd->rev[1],
+	       "* 91 Revision Code *");
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       93, 94, spd->mdate[0], spd->mdate[1],
+	       "* 93 Manufacturing Date *");
+	printf("%-3d-%3d: ", 95, 98);
+
+	for (i = 0; i < 4; i++) {
+		printf("%02x", spd->sernum[i]);
+	}
+	printf("* 95 Assembly Serial Number *\n");
+
+	printf("%-3d-%3d: ", 99, 127);
+	for (i = 0; i < 27; i++) {
+		printf("%02x", spd->mspec[i]);
+	}
+
+	printf("* 99 Manufacturer Specific Data *\n");
+}
+
+void
+ddr2_spd_dump(const ddr2_spd_eeprom_t *spd)
+{
+	unsigned int i;
+
+	printf("%-3d    : %02x %s\n",
+	       0, spd->info_size,
+	       " spd->info_size,   *  0 # bytes written into serial memory *");
+	printf("%-3d    : %02x %s\n",
+	       1, spd->chip_size,
+	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
+	printf("%-3d    : %02x %s\n",
+	       2, spd->mem_type,
+	       " spd->mem_type,    *  2 Fundamental memory type *");
+	printf("%-3d    : %02x %s\n",
+	       3, spd->nrow_addr,
+	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       4, spd->ncol_addr,
+	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       5, spd->mod_ranks,
+	       " spd->mod_ranks    *  5 # of Module Rows on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       6, spd->dataw,
+	       " spd->dataw,       *  6 Data Width of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       7, spd->res_7,
+	       " spd->res_7,       *  7 Reserved *");
+	printf("%-3d    : %02x %s\n",
+	       8, spd->voltage,
+	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       9, spd->clk_cycle,
+	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       10, spd->clk_access,
+	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       11, spd->config,
+	       " spd->config,      * 11 DIMM Configuration type *");
+	printf("%-3d    : %02x %s\n",
+	       12, spd->refresh,
+	       " spd->refresh,     * 12 Refresh Rate/Type *");
+	printf("%-3d    : %02x %s\n",
+	       13, spd->primw,
+	       " spd->primw,       * 13 Primary SDRAM Width *");
+	printf("%-3d    : %02x %s\n",
+	       14, spd->ecw,
+	       " spd->ecw,         * 14 Error Checking SDRAM width *");
+	printf("%-3d    : %02x %s\n",
+	       15, spd->res_15,
+	       " spd->res_15,   * 15 Reserved *");
+	printf("%-3d    : %02x %s\n",
+	       16, spd->burstl,
+	       " spd->burstl,      * 16 Burst Lengths Supported *");
+	printf("%-3d    : %02x %s\n",
+	       17, spd->nbanks,
+	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
+	printf("%-3d    : %02x %s\n",
+	       18, spd->cas_lat,
+	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
+	printf("%-3d    : %02x %s\n",
+	       19, spd->mech_char,
+	       " spd->mech_char,   * 19 Mechanical Characteristics *");
+	printf("%-3d    : %02x %s\n",
+	       20, spd->dimm_type,
+	       " spd->dimm_type,   * 20 DIMM type *");
+	printf("%-3d    : %02x %s\n",
+	       21, spd->mod_attr,
+	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       22, spd->dev_attr,
+	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       23, spd->clk_cycle2,
+	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       24, spd->clk_access2,
+	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       25, spd->clk_cycle3,
+	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       26, spd->clk_access3,
+	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       27, spd->trp,
+	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
+	printf("%-3d    : %02x %s\n",
+	       28, spd->trrd,
+	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
+	printf("%-3d    : %02x %s\n",
+	       29, spd->trcd,
+	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
+	printf("%-3d    : %02x %s\n",
+	       30, spd->tras,
+	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
+	printf("%-3d    : %02x %s\n",
+	       31, spd->rank_dens,
+	       " spd->rank_dens,   * 31 Density of each rank on module *");
+	printf("%-3d    : %02x %s\n",
+	       32, spd->ca_setup,
+	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       33, spd->ca_hold,
+	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       34, spd->data_setup,
+	       " spd->data_setup,  * 34 Data signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       35, spd->data_hold,
+	       " spd->data_hold,   * 35 Data signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       36, spd->twr,
+	       " spd->twr,         * 36 Write Recovery time tWR *");
+	printf("%-3d    : %02x %s\n",
+	       37, spd->twtr,
+	       " spd->twtr,        * 37 Int write to read delay tWTR *");
+	printf("%-3d    : %02x %s\n",
+	       38, spd->trtp,
+	       " spd->trtp,        * 38 Int read to precharge delay tRTP *");
+	printf("%-3d    : %02x %s\n",
+	       39, spd->mem_probe,
+	       " spd->mem_probe,   * 39 Mem analysis probe characteristics *");
+	printf("%-3d    : %02x %s\n",
+	       40, spd->trctrfc_ext,
+	       " spd->trctrfc_ext, * 40 Extensions to trc and trfc *");
+	printf("%-3d    : %02x %s\n",
+	       41, spd->trc,
+	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
+	printf("%-3d    : %02x %s\n",
+	       42, spd->trfc,
+	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
+	printf("%-3d    : %02x %s\n",
+	       43, spd->tckmax,
+	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
+	printf("%-3d    : %02x %s\n",
+	       44, spd->tdqsq,
+	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
+	printf("%-3d    : %02x %s\n",
+	       45, spd->tqhs,
+	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
+	printf("%-3d    : %02x %s\n",
+	       46, spd->pll_relock,
+	       " spd->pll_relock,  * 46 PLL Relock time *");
+	printf("%-3d    : %02x %s\n",
+	       47, spd->Tcasemax,
+	       " spd->Tcasemax,    * 47 Tcasemax *");
+	printf("%-3d    : %02x %s\n",
+	       48, spd->psiTAdram,
+	       " spd->psiTAdram,   * 48 Thermal Resistance of DRAM Package "
+	       "from Top (Case) to Ambient (Psi T-A DRAM) *");
+	printf("%-3d    : %02x %s\n",
+	       49, spd->dt0_mode,
+	       " spd->dt0_mode,    * 49 DRAM Case Temperature Rise from "
+	       "Ambient due to Activate-Precharge/Mode Bits "
+	       "(DT0/Mode Bits) *)");
+	printf("%-3d    : %02x %s\n",
+	       50, spd->dt2n_dt2q,
+	       " spd->dt2n_dt2q,   * 50 DRAM Case Temperature Rise from "
+	       "Ambient due to Precharge/Quiet Standby "
+	       "(DT2N/DT2Q) *");
+	printf("%-3d    : %02x %s\n",
+	       51, spd->dt2p,
+	       " spd->dt2p,        * 51 DRAM Case Temperature Rise from "
+	       "Ambient due to Precharge Power-Down (DT2P) *");
+	printf("%-3d    : %02x %s\n",
+	       52, spd->dt3n,
+	       " spd->dt3n,        * 52 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Standby (DT3N) *");
+	printf("%-3d    : %02x %s\n",
+	       53, spd->dt3pfast,
+	       " spd->dt3pfast,    * 53 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Power-Down with Fast PDN Exit "
+	       "(DT3Pfast) *");
+	printf("%-3d    : %02x %s\n",
+	       54, spd->dt3pslow,
+	       " spd->dt3pslow,    * 54 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Power-Down with Slow PDN Exit "
+	       "(DT3Pslow) *");
+	printf("%-3d    : %02x %s\n",
+	       55, spd->dt4r_dt4r4w,
+	       " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from "
+	       "Ambient due to Page Open Burst Read/DT4R4W Mode Bit "
+	       "(DT4R/DT4R4W Mode Bit) *");
+	printf("%-3d    : %02x %s\n",
+	       56, spd->dt5b,
+	       " spd->dt5b,        * 56 DRAM Case Temperature Rise from "
+	       "Ambient due to Burst Refresh (DT5B) *");
+	printf("%-3d    : %02x %s\n",
+	       57, spd->dt7,
+	       " spd->dt7,         * 57 DRAM Case Temperature Rise from "
+	       "Ambient due to Bank Interleave Reads with "
+	       "Auto-Precharge (DT7) *");
+	printf("%-3d    : %02x %s\n",
+	       58, spd->psiTApll,
+	       " spd->psiTApll,    * 58 Thermal Resistance of PLL Package form"
+	       " Top (Case) to Ambient (Psi T-A PLL) *");
+	printf("%-3d    : %02x %s\n",
+	       59, spd->psiTAreg,
+	       " spd->psiTAreg,    * 59 Thermal Reisitance of Register Package"
+	       " from Top (Case) to Ambient (Psi T-A Register) *");
+	printf("%-3d    : %02x %s\n",
+	       60, spd->dtpllactive,
+	       " spd->dtpllactive, * 60 PLL Case Temperature Rise from "
+	       "Ambient due to PLL Active (DT PLL Active) *");
+	printf("%-3d    : %02x %s\n",
+	       61, spd->dtregact,
+	       " spd->dtregact,    "
+	       "* 61 Register Case Temperature Rise from Ambient due to "
+	       "Register Active/Mode Bit (DT Register Active/Mode Bit) *");
+	printf("%-3d    : %02x %s\n",
+	       62, spd->spd_rev,
+	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
+	printf("%-3d    : %02x %s\n",
+	       63, spd->cksum,
+	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
+	printf("%-3d-%3d: ",  64, 71);
+
+	for (i = 0; i < 8; i++) {
+		printf("%02x", spd->mid[i]);
+	}
+
+	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+	printf("%-3d    : %02x %s\n",
+	       72, spd->mloc,
+	       " spd->mloc,        * 72 Manufacturing Location *");
+
+	printf("%-3d-%3d: >>",  73, 90);
+	for (i = 0; i < 18; i++) {
+		printf("%c", spd->mpart[i]);
+	}
+
+	printf("<<* 73 Manufacturer's Part Number *\n");
+
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       91, 92, spd->rev[0], spd->rev[1],
+	       "* 91 Revision Code *");
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       93, 94, spd->mdate[0], spd->mdate[1],
+	       "* 93 Manufacturing Date *");
+	printf("%-3d-%3d: ", 95, 98);
+
+	for (i = 0; i < 4; i++) {
+		printf("%02x", spd->sernum[i]);
+	}
+	printf("* 95 Assembly Serial Number *\n");
+
+	printf("%-3d-%3d: ", 99, 127);
+	for (i = 0; i < 27; i++) {
+		printf("%02x", spd->mspec[i]);
+	}
+
+	printf("* 99 Manufacturer Specific Data *\n");
+}
+
+/* used for ddr1 and ddr2 spd */
+static int
+spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum)
+{
+	unsigned int cksum = 0;
+	unsigned int i;
+
+	/*
+	 * Check SPD revision supported
+	 * Rev 1.2 or less supported by this code
+	 */
+	if (spd_rev > 0x12) {
+		printf("SPD revision %02X not supported by this code\n",
+		       spd_rev);
+		return 1;
+	}
+
+	/*
+	 * Calculate checksum
+	 */
+	for (i = 0; i < 63; i++) {
+		cksum += *buf++;
+	}
+	cksum &= 0xFF;
+
+	if (cksum != spd_cksum) {
+		printf("SPD checksum unexpected. "
+			"Checksum in SPD = %02X, computed SPD = %02X\n",
+			spd_cksum, cksum);
+		return 1;
+	}
+
+	return 0;
+}
+
+unsigned int
+ddr1_spd_check(const ddr1_spd_eeprom_t *spd)
+{
+	const u8 *p = (const u8 *)spd;
+
+	return spd_check(p, spd->spd_rev, spd->cksum);
+}
+
+unsigned int
+ddr2_spd_check(const ddr2_spd_eeprom_t *spd)
+{
+	const u8 *p = (const u8 *)spd;
+
+	return spd_check(p, spd->spd_rev, spd->cksum);
+}
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
new file mode 100644
index 0000000..6fdcef0
--- /dev/null
+++ b/include/ddr_spd.h
@@ -0,0 +1,292 @@
+/*
+ * 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 _DDR_SPD_H_
+#define _DDR_SPD_H_
+
+/*
+ * Format from "JEDEC Standard No. 21-C,
+ * Appendix D: Rev 1.0: SPD's for DDR SDRAM
+ */
+typedef struct ddr1_spd_eeprom_s {
+	unsigned char info_size;   /*  0 # bytes written into serial memory */
+	unsigned char chip_size;   /*  1 Total # bytes of SPD memory device */
+	unsigned char mem_type;    /*  2 Fundamental memory type */
+	unsigned char nrow_addr;   /*  3 # of Row Addresses on this assembly */
+	unsigned char ncol_addr;   /*  4 # of Column Addrs on this assembly */
+	unsigned char nrows;       /*  5 Number of DIMM Banks */
+	unsigned char dataw_lsb;   /*  6 Data Width of this assembly */
+	unsigned char dataw_msb;   /*  7 ... Data Width continuation */
+	unsigned char voltage;     /*  8 Voltage intf std of this assembly */
+	unsigned char clk_cycle;   /*  9 SDRAM Cycle time @ CL=X */
+	unsigned char clk_access;  /* 10 SDRAM Access from Clk @ CL=X (tAC) */
+	unsigned char config;      /* 11 DIMM Configuration type */
+	unsigned char refresh;     /* 12 Refresh Rate/Type */
+	unsigned char primw;       /* 13 Primary SDRAM Width */
+	unsigned char ecw;         /* 14 Error Checking SDRAM width */
+	unsigned char min_delay;   /* 15 for Back to Back Random Address */
+	unsigned char burstl;      /* 16 Burst Lengths Supported */
+	unsigned char nbanks;      /* 17 # of Banks on SDRAM Device */
+	unsigned char cas_lat;     /* 18 CAS# Latencies Supported */
+	unsigned char cs_lat;      /* 19 CS# Latency */
+	unsigned char write_lat;   /* 20 Write Latency (aka Write Recovery) */
+	unsigned char mod_attr;    /* 21 SDRAM Module Attributes */
+	unsigned char dev_attr;    /* 22 SDRAM Device Attributes */
+	unsigned char clk_cycle2;  /* 23 Min SDRAM Cycle time @ CL=X-0.5 */
+	unsigned char clk_access2; /* 24 SDRAM Access from
+				         Clk @ CL=X-0.5 (tAC) */
+	unsigned char clk_cycle3;  /* 25 Min SDRAM Cycle time @ CL=X-1 */
+	unsigned char clk_access3; /* 26 Max Access from Clk @ CL=X-1 (tAC) */
+	unsigned char trp;         /* 27 Min Row Precharge Time (tRP)*/
+	unsigned char trrd;        /* 28 Min Row Active to Row Active (tRRD) */
+	unsigned char trcd;        /* 29 Min RAS to CAS Delay (tRCD) */
+	unsigned char tras;        /* 30 Minimum RAS Pulse Width (tRAS) */
+	unsigned char bank_dens;   /* 31 Density of each bank on module */
+	unsigned char ca_setup;    /* 32 Addr + Cmd Setup Time Before Clk */
+	unsigned char ca_hold;     /* 33 Addr + Cmd Hold Time After Clk */
+	unsigned char data_setup;  /* 34 Data Input Setup Time Before Strobe */
+	unsigned char data_hold;   /* 35 Data Input Hold Time After Strobe */
+	unsigned char res_36_40[5];/* 36-40 reserved for VCSDRAM */
+	unsigned char trc;         /* 41 Min Active to Auto refresh time tRC */
+	unsigned char trfc;        /* 42 Min Auto to Active period tRFC */
+	unsigned char tckmax;      /* 43 Max device cycle time tCKmax */
+	unsigned char tdqsq;       /* 44 Max DQS to DQ skew (tDQSQ max) */
+	unsigned char tqhs;        /* 45 Max Read DataHold skew (tQHS) */
+	unsigned char res_46;      /* 46 Reserved */
+	unsigned char dimm_height; /* 47 DDR SDRAM DIMM Height */
+	unsigned char res_48_61[14]; /* 48-61 Reserved */
+	unsigned char spd_rev;     /* 62 SPD Data Revision Code */
+	unsigned char cksum;       /* 63 Checksum for bytes 0-62 */
+	unsigned char mid[8];      /* 64-71 Mfr's JEDEC ID code per JEP-106 */
+	unsigned char mloc;        /* 72 Manufacturing Location */
+	unsigned char mpart[18];   /* 73 Manufacturer's Part Number */
+	unsigned char rev[2];      /* 91 Revision Code */
+	unsigned char mdate[2];    /* 93 Manufacturing Date */
+	unsigned char sernum[4];   /* 95 Assembly Serial Number */
+	unsigned char mspec[27];   /* 99-127 Manufacturer Specific Data */
+
+} ddr1_spd_eeprom_t;
+
+/*
+ * Format from "JEDEC Appendix X: Serial Presence Detects for DDR2 SDRAM",
+ * SPD Revision 1.2
+ */
+typedef struct ddr2_spd_eeprom_s {
+	unsigned char info_size;   /*  0 # bytes written into serial memory */
+	unsigned char chip_size;   /*  1 Total # bytes of SPD memory device */
+	unsigned char mem_type;    /*  2 Fundamental memory type */
+	unsigned char nrow_addr;   /*  3 # of Row Addresses on this assembly */
+	unsigned char ncol_addr;   /*  4 # of Column Addrs on this assembly */
+	unsigned char mod_ranks;   /*  5 Number of DIMM Ranks */
+	unsigned char dataw;       /*  6 Module Data Width */
+	unsigned char res_7;       /*  7 Reserved */
+	unsigned char voltage;     /*  8 Voltage intf std of this assembly */
+	unsigned char clk_cycle;   /*  9 SDRAM Cycle time @ CL=X */
+	unsigned char clk_access;  /* 10 SDRAM Access from Clk @ CL=X (tAC) */
+	unsigned char config;      /* 11 DIMM Configuration type */
+	unsigned char refresh;     /* 12 Refresh Rate/Type */
+	unsigned char primw;       /* 13 Primary SDRAM Width */
+	unsigned char ecw;         /* 14 Error Checking SDRAM width */
+	unsigned char res_15;      /* 15 Reserved */
+	unsigned char burstl;      /* 16 Burst Lengths Supported */
+	unsigned char nbanks;      /* 17 # of Banks on Each SDRAM Device */
+	unsigned char cas_lat;     /* 18 CAS# Latencies Supported */
+	unsigned char mech_char;   /* 19 DIMM Mechanical Characteristics */
+	unsigned char dimm_type;   /* 20 DIMM type information */
+	unsigned char mod_attr;    /* 21 SDRAM Module Attributes */
+	unsigned char dev_attr;    /* 22 SDRAM Device Attributes */
+	unsigned char clk_cycle2;  /* 23 Min SDRAM Cycle time @ CL=X-1 */
+	unsigned char clk_access2; /* 24 SDRAM Access from Clk @ CL=X-1 (tAC) */
+	unsigned char clk_cycle3;  /* 25 Min SDRAM Cycle time @ CL=X-2 */
+	unsigned char clk_access3; /* 26 Max Access from Clk @ CL=X-2 (tAC) */
+	unsigned char trp;         /* 27 Min Row Precharge Time (tRP)*/
+	unsigned char trrd;        /* 28 Min Row Active to Row Active (tRRD) */
+	unsigned char trcd;        /* 29 Min RAS to CAS Delay (tRCD) */
+	unsigned char tras;        /* 30 Minimum RAS Pulse Width (tRAS) */
+	unsigned char rank_dens;   /* 31 Density of each rank on module */
+	unsigned char ca_setup;    /* 32 Addr+Cmd Setup Time Before Clk (tIS) */
+	unsigned char ca_hold;     /* 33 Addr+Cmd Hold Time After Clk (tIH) */
+	unsigned char data_setup;  /* 34 Data Input Setup Time
+				         Before Strobe (tDS) */
+	unsigned char data_hold;   /* 35 Data Input Hold Time
+				         After Strobe (tDH) */
+	unsigned char twr;         /* 36 Write Recovery time tWR */
+	unsigned char twtr;        /* 37 Int write to read delay tWTR */
+	unsigned char trtp;        /* 38 Int read to precharge delay tRTP */
+	unsigned char mem_probe;   /* 39 Mem analysis probe characteristics */
+	unsigned char trctrfc_ext; /* 40 Extensions to trc and trfc */
+	unsigned char trc;         /* 41 Min Active to Auto refresh time tRC */
+	unsigned char trfc;        /* 42 Min Auto to Active period tRFC */
+	unsigned char tckmax;      /* 43 Max device cycle time tCKmax */
+	unsigned char tdqsq;       /* 44 Max DQS to DQ skew (tDQSQ max) */
+	unsigned char tqhs;        /* 45 Max Read DataHold skew (tQHS) */
+	unsigned char pll_relock;  /* 46 PLL Relock time */
+	unsigned char Tcasemax;    /* 47 Tcasemax */
+	unsigned char psiTAdram;   /* 48 Thermal Resistance of DRAM Package from
+				         Top (Case) to Ambient (Psi T-A DRAM) */
+	unsigned char dt0_mode;    /* 49 DRAM Case Temperature Rise from Ambient
+				         due to Activate-Precharge/Mode Bits
+					 (DT0/Mode Bits) */
+	unsigned char dt2n_dt2q;   /* 50 DRAM Case Temperature Rise from Ambient
+				         due to Precharge/Quiet Standby
+					 (DT2N/DT2Q) */
+	unsigned char dt2p;        /* 51 DRAM Case Temperature Rise from Ambient
+				         due to Precharge Power-Down (DT2P) */
+	unsigned char dt3n;        /* 52 DRAM Case Temperature Rise from Ambient
+				         due to Active Standby (DT3N) */
+	unsigned char dt3pfast;    /* 53 DRAM Case Temperature Rise from Ambient
+				         due to Active Power-Down with
+					 Fast PDN Exit (DT3Pfast) */
+	unsigned char dt3pslow;    /* 54 DRAM Case Temperature Rise from Ambient
+				         due to Active Power-Down with Slow
+					 PDN Exit (DT3Pslow) */
+	unsigned char dt4r_dt4r4w; /* 55 DRAM Case Temperature Rise from Ambient
+				         due to Page Open Burst Read/DT4R4W
+					 Mode Bit (DT4R/DT4R4W Mode Bit) */
+	unsigned char dt5b;        /* 56 DRAM Case Temperature Rise from Ambient
+				         due to Burst Refresh (DT5B) */
+	unsigned char dt7;         /* 57 DRAM Case Temperature Rise from Ambient
+				         due to Bank Interleave Reads with
+					 Auto-Precharge (DT7) */
+	unsigned char psiTApll;    /* 58 Thermal Resistance of PLL Package form
+				         Top (Case) to Ambient (Psi T-A PLL) */
+	unsigned char psiTAreg;    /* 59 Thermal Reisitance of Register Package
+				         from Top (Case) to Ambient
+					 (Psi T-A Register) */
+	unsigned char dtpllactive; /* 60 PLL Case Temperature Rise from Ambient
+				         due to PLL Active (DT PLL Active) */
+	unsigned char dtregact;    /* 61 Register Case Temperature Rise from
+				         Ambient due to Register Active/Mode Bit
+					 (DT Register Active/Mode Bit) */
+	unsigned char spd_rev;     /* 62 SPD Data Revision Code */
+	unsigned char cksum;       /* 63 Checksum for bytes 0-62 */
+	unsigned char mid[8];      /* 64 Mfr's JEDEC ID code per JEP-106 */
+	unsigned char mloc;        /* 72 Manufacturing Location */
+	unsigned char mpart[18];   /* 73 Manufacturer's Part Number */
+	unsigned char rev[2];      /* 91 Revision Code */
+	unsigned char mdate[2];    /* 93 Manufacturing Date */
+	unsigned char sernum[4];   /* 95 Assembly Serial Number */
+	unsigned char mspec[27];   /* 99-127 Manufacturer Specific Data */
+
+} ddr2_spd_eeprom_t;
+
+typedef struct ddr3_spd_eeprom_s {
+	/* General Section: Bytes 0-59 */
+	unsigned char info_size_crc;   /*  0 # bytes written into serial memory,
+					     CRC coverage */
+	unsigned char spd_rev;         /*  1 Total # bytes of SPD mem device */
+	unsigned char mem_type;        /*  2 Key Byte / Fundamental mem type */
+	unsigned char module_type;     /*  3 Key Byte / Module Type */
+	unsigned char density_banks;   /*  4 SDRAM Density and Banks */
+	unsigned char addressing;      /*  5 SDRAM Addressing */
+	unsigned char res_6;           /*  6 Reserved */
+	unsigned char organization;    /*  7 Module Organization */
+	unsigned char bus_width;       /*  8 Module Memory Bus Width */
+	unsigned char ftb_div;         /*  9 Fine Timebase (FTB)
+					     Dividend / Divisor */
+	unsigned char mtb_dividend;    /* 10 Medium Timebase (MTB) Dividend */
+	unsigned char mtb_divisor;     /* 11 Medium Timebase (MTB) Divisor */
+	unsigned char tCK_min;         /* 12 SDRAM Minimum Cycle Time */
+	unsigned char res_13;          /* 13 Reserved */
+	unsigned char caslat_lsb;      /* 14 CAS Latencies Supported,
+					     Least Significant Byte */
+	unsigned char caslat_msb;      /* 15 CAS Latencies Supported,
+					     Most Significant Byte */
+	unsigned char tAA_min;         /* 16 Min CAS Latency Time */
+	unsigned char tWR_min;         /* 17 Min Write REcovery Time */
+	unsigned char tRCD_min;        /* 18 Min RAS# to CAS# Delay Time */
+	unsigned char tRRD_min;        /* 19 Min Row Active to
+					     Row Active Delay Time */
+	unsigned char tRP_min;         /* 20 Min Row Precharge Delay Time */
+	unsigned char tRAS_tRC_ext;    /* 21 Upper Nibbles for tRAS and tRC */
+	unsigned char tRAS_min_lsb;    /* 22 Min Active to Precharge
+					     Delay Time */
+	unsigned char tRC_min_lsb;     /* 23 Min Active to Active/Refresh
+					     Delay Time, LSB */
+	unsigned char tRFC_min_lsb;    /* 24 Min Refresh Recovery Delay Time */
+	unsigned char tRFC_min_msb;    /* 25 Min Refresh Recovery Delay Time */
+	unsigned char tWTR_min;        /* 26 Min Internal Write to
+					     Read Command Delay Time */
+	unsigned char tRTP_min;        /* 27 Min Internal Read to Precharge
+					     Command Delay Time */
+	unsigned char tFAW_msb;        /* 28 Upper Nibble for tFAW */
+	unsigned char tFAW_min;        /* 29 Min Four Activate Window
+					     Delay Time*/
+	unsigned char opt_features;    /* 30 SDRAM Optional Features */
+	unsigned char therm_ref_opt;   /* 31 SDRAM Thermal and Refresh Opts */
+	unsigned char res_32_59[28];   /* 32-59 Reserved, General Section */
+
+	/* Module-Specific Section: Bytes 60-116 */
+	union {
+		struct {
+			/* 60 (Unbuffered) Module Nominal Height */
+			unsigned char mod_height;
+			/* 61 (Unbuffered) Module Maximum Thickness */
+			unsigned char mod_thickness;
+			/* 62 (Unbuffered) Reference Raw Card Used */
+			unsigned char ref_raw_card;
+			/* 63 (Unbuffered) Address Mapping from
+			      Edge Connector to DRAM */
+			unsigned char addr_mapping;
+			/* 64-116 (Unbuffered) Reserved */
+			unsigned char res_64_116[53];
+		} unbuffered;
+		struct {
+			/* 60 (Registered) Module Nominal Height */
+			unsigned char mod_height;
+			/* 61 (Registered) Module Maximum Thickness */
+			unsigned char mod_thickness;
+			/* 62 (Registered) Reference Raw Card Used */
+			unsigned char ref_raw_card;
+		} registered;
+		unsigned char uc[57]; /* 60-116 Module-Specific Section */
+	} mod_section;
+
+	/* Unique Module ID: Bytes 117-125 */
+	unsigned char mmid_lsb;        /* 117 Module MfgID Code LSB - JEP-106 */
+	unsigned char mmid_msb;        /* 118 Module MfgID Code MSB - JEP-106 */
+	unsigned char mloc;            /* 119 Mfg Location */
+	unsigned char mdate[2];        /* 120-121 Mfg Date */
+	unsigned char sernum[4];       /* 122-125 Module Serial Number */
+
+	/* CRC: Bytes 126-127 */
+	unsigned char crc[2];          /* 126-127 SPD CRC */
+
+	/* Other Manufacturer Fields and User Space: Bytes 128-255 */
+	unsigned char mpart[18];       /* 128-145 Mfg's Module Part Number */
+	unsigned char mrev[2];         /* 146-147 Module Revision Code */
+
+	unsigned char dmid_lsb;        /* 148 DRAM MfgID Code LSB - JEP-106 */
+	unsigned char dmid_msb;        /* 149 DRAM MfgID Code MSB - JEP-106 */
+
+	unsigned char msd[26];         /* 150-175 Mfg's Specific Data */
+	unsigned char cust[80];        /* 176-255 Open for Customer Use */
+
+} ddr3_spd_eeprom_t;
+
+extern unsigned int ddr1_spd_check(const ddr1_spd_eeprom_t *spd);
+extern void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd);
+extern unsigned int ddr2_spd_check(const ddr2_spd_eeprom_t *spd);
+extern void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd);
+
+/*
+ * Byte 2 Fundamental Memory Types.
+ */
+#define SPD_MEMTYPE_FPM		(0x01)
+#define SPD_MEMTYPE_EDO		(0x02)
+#define SPD_MEMTYPE_PIPE_NIBBLE	(0x03)
+#define SPD_MEMTYPE_SDRAM	(0x04)
+#define SPD_MEMTYPE_ROM		(0x05)
+#define SPD_MEMTYPE_SGRAM	(0x06)
+#define SPD_MEMTYPE_DDR		(0x07)
+#define SPD_MEMTYPE_DDR2	(0x08)
+#define SPD_MEMTYPE_DDR2_FBDIMM	(0x09)
+#define SPD_MEMTYPE_DDR2_FBDIMM_PROBE	(0x0A)
+#define SPD_MEMTYPE_DDR3	(0x0B)
+
+#endif /* _DDR_SPD_H_ */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code.
  2008-08-20 23:22 [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Kumar Gala
@ 2008-08-20 23:22 ` Kumar Gala
  2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
                     ` (2 more replies)
  2008-08-26 23:07 ` [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Wolfgang Denk
  1 sibling, 3 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Signed-off-by: James Yang <James.Yang@freescale.com>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
Signed-off-by: Ed Swarthout <Ed.Swarthout@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 cpu/mpc85xx/Makefile               |    9 +
 cpu/mpc86xx/Makefile               |    4 +
 cpu/mpc8xxx/Makefile               |   29 +
 cpu/mpc8xxx/common_timing_params.h |   55 ++
 cpu/mpc8xxx/ddr2_dimm_params.h     |   86 +++
 cpu/mpc8xxx/fsl_ddr_ctrl.c         | 1002 +++++++++++++++++++++++++++++++
 cpu/mpc8xxx/fsl_ddr_sdram.c        | 1134 ++++++++++++++++++++++++++++++++++++
 cpu/mpc8xxx/fsl_ddr_sdram.h        |   90 +++
 cpu/mpc8xxx/fsl_memctrl.h          |   44 ++
 cpu/mpc8xxx/fsl_util.c             |   59 ++
 cpu/mpc8xxx/memctl_options.h       |   85 +++
 11 files changed, 2597 insertions(+), 0 deletions(-)
 create mode 100644 cpu/mpc8xxx/Makefile
 create mode 100644 cpu/mpc8xxx/common_timing_params.h
 create mode 100644 cpu/mpc8xxx/ddr2_dimm_params.h
 create mode 100644 cpu/mpc8xxx/fsl_ddr_ctrl.c
 create mode 100644 cpu/mpc8xxx/fsl_ddr_sdram.c
 create mode 100644 cpu/mpc8xxx/fsl_ddr_sdram.h
 create mode 100644 cpu/mpc8xxx/fsl_memctrl.h
 create mode 100644 cpu/mpc8xxx/fsl_util.c
 create mode 100644 cpu/mpc8xxx/memctl_options.h

diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
index adbc585..c180dbd 100644
--- a/cpu/mpc85xx/Makefile
+++ b/cpu/mpc85xx/Makefile
@@ -33,6 +33,15 @@ SOBJS-$(CONFIG_MP) += release.o
 SOBJS	= $(SOBJS-y)
 COBJS-$(CONFIG_MP) += mp.o
 COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+
+ifneq ($(CONFIG_FSL_DDR3),y)
+ifneq ($(CONFIG_FSL_DDR2),y)
+ifneq ($(CONFIG_FSL_DDR1),y)
+COBJS-y	+= spd_sdram.o
+endif
+endif
+endif
+
 COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o tlb.o \
 	  pci.o serial_scc.o commproc.o ether_fcc.o spd_sdram.o qe_io.o \
 	  $(COBJS-y)
diff --git a/cpu/mpc86xx/Makefile b/cpu/mpc86xx/Makefile
index 537f62a..4227053 100644
--- a/cpu/mpc86xx/Makefile
+++ b/cpu/mpc86xx/Makefile
@@ -40,6 +40,10 @@ COBJS-y	+= spd_sdram.o
 
 COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
 
+ifneq ($(CONFIG_FSL_DDR2),y)
+COBJS-y	+= spd_sdram.o
+endif
+
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
 START	:= $(addprefix $(obj),$(START))
diff --git a/cpu/mpc8xxx/Makefile b/cpu/mpc8xxx/Makefile
new file mode 100644
index 0000000..888ebfe
--- /dev/null
+++ b/cpu/mpc8xxx/Makefile
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libmpc8xxx.a
+
+COBJS-$(CONFIG_FSL_DDR1)	+= fsl_ddr_sdram.o fsl_util.o fsl_ddr_ctrl.o
+COBJS-$(CONFIG_FSL_DDR1)	+= fsl_ddr1.o
+
+COBJS-$(CONFIG_FSL_DDR2)	+= fsl_ddr_sdram.o fsl_util.o fsl_ddr_ctrl.o
+COBJS-$(CONFIG_FSL_DDR2)	+= fsl_ddr2.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/cpu/mpc8xxx/common_timing_params.h b/cpu/mpc8xxx/common_timing_params.h
new file mode 100644
index 0000000..611ffe1
--- /dev/null
+++ b/cpu/mpc8xxx/common_timing_params.h
@@ -0,0 +1,55 @@
+/*
+ * 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 COMMON_TIMING_PARAMS_H
+#define COMMON_TIMING_PARAMS_H
+
+#include "fsl_ddr_sdram.h"
+
+typedef struct {
+	/* parameters to constrict */
+
+	unsigned int tCKmin_X_ps;
+	unsigned int tCKmax_ps;
+	unsigned int tCKmax_max_ps;
+	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;	/* maximum = 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 */
+
+	unsigned int ndimms_present;
+	unsigned int lowest_common_SPD_caslat;
+	unsigned int highest_common_derated_caslat;
+	unsigned int additive_latency;
+	unsigned int all_DIMMs_burst_lengths_bitmask;
+	unsigned int all_DIMMs_registered;
+	unsigned int all_DIMMs_unbuffered;
+	unsigned int all_DIMMs_ECC_capable;
+
+	unsigned long long total_mem;
+	unsigned long long base_address;
+} common_timing_params_t;
+
+#endif
diff --git a/cpu/mpc8xxx/ddr2_dimm_params.h b/cpu/mpc8xxx/ddr2_dimm_params.h
new file mode 100644
index 0000000..2ac8183
--- /dev/null
+++ b/cpu/mpc8xxx/ddr2_dimm_params.h
@@ -0,0 +1,86 @@
+/*
+ * 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
+
+#include "fsl_ddr_sdram.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/fsl_ddr_ctrl.c b/cpu/mpc8xxx/fsl_ddr_ctrl.c
new file mode 100644
index 0000000..4eca701
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr_ctrl.c
@@ -0,0 +1,1002 @@
+/*
+ * 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+
+#include "fsl_ddr_sdram.h"
+
+extern unsigned int picos_to_mclk(unsigned int picos);
+extern unsigned int fsl_ddr_type_function(void);
+/*
+ * Determine Rtt value.
+ *
+ * This should likely be either board or controller specific.
+ *
+ * Rtt(nominal):
+ *	0 = Rtt disabled
+ *	1 = 75 ohm
+ *	2 = 150 ohm
+ *	3 = 50 ohm
+ *
+ * FIXME: Apparently 8641 needs a value of 2
+ * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
+ *
+ * FIXME: There was some effort down this line earlier:
+ *
+ *	unsigned int i;
+ *	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
+ *		if (popts->dimmslot[i].num_valid_cs
+ *		    && (popts->cs_local_opts[2*i].odt_rd_cfg
+ *			|| popts->cs_local_opts[2*i].odt_wr_cfg)) {
+ *			rtt = 2;
+ *			break;
+ *		}
+ *	}
+ */
+static inline int fsl_ddr_get_rtt(void)
+{
+	int rtt;
+
+#if defined(CONFIG_FSL_DDR1)
+	rtt = 0;
+#elif defined(CONFIG_FSL_DDR2)
+	rtt = 3;
+#else
+#error "Need Rtt value for DDR3"
+#endif
+
+	return rtt;
+}
+
+/* Chip Select Configuration (CSn_CONFIG) */
+static void set_csn_config(int i, fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const dimm_params_t *dimm_params)
+{
+	unsigned int cs_n_en = 0; /* Chip Select enable */
+	unsigned int intlv_en = 0; /* Memory controller interleave enable */
+	unsigned int intlv_ctl = 0; /* Interleaving control */
+	unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
+	unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
+	unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
+	unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
+	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
+	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
+
+	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
+	if ((((i&1) == 0)
+	    && (dimm_params[i/2].n_ranks == 1))
+	    || (dimm_params[i/2].n_ranks == 2)) {
+		unsigned int n_banks_per_sdram_device;
+		cs_n_en = 1;
+		if (i == 0) {
+			/* These fields only available in CS0_CONFIG */
+			intlv_en = popts->memctl_interleaving;
+			intlv_ctl = popts->memctl_interleaving_mode;
+		}
+		ap_n_en = popts->cs_local_opts[i].auto_precharge;
+		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
+		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+		n_banks_per_sdram_device
+			= dimm_params[i/2].n_banks_per_sdram_device;
+		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+		row_bits_cs_n = dimm_params[i/2].n_row_addr - 12;
+		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)
+		| ((ap_n_en & 0x1) << 23)
+
+		/* XXX: some implementation only have 1 bit starting at left */
+		| ((odt_rd_cfg & 0x7) << 20)
+
+		/* XXX: Some implementation only have 1 bit starting@left */
+		| ((odt_wr_cfg & 0x7) << 16)
+
+		| ((ba_bits_cs_n & 0x3) << 14)
+		| ((row_bits_cs_n & 0x7) << 8)
+		| ((col_bits_cs_n & 0x7) << 0)
+		);
+}
+
+/* Chip Select Configuration 2 (CSn_CONFIG_2) */
+/* FIXME: 8572 */
+static void set_csn_config_2(int i, fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int pasr_cfg = 0;	/* Partial array self refresh config */
+
+	ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
+}
+
+/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
+
+#if defined(CONFIG_FSL_DDR2)
+/*
+ * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
+ *
+ * Avoid writing for DDR I.  The new PQ38 DDR controller
+ * dreams up non-zero default values to be backwards compatible.
+ */
+static void set_timing_cfg_0(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
+	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
+	/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
+	unsigned char trrt_mclk = 0;   /* Read-to-read turnaround */
+	unsigned char twwt_mclk = 0;   /* Write-to-write turnaround */
+
+	/* Active powerdown exit timing (tXARD and tXARDS). */
+	unsigned char act_pd_exit_mclk;
+	/* Precharge powerdown exit timing (tXP). */
+	unsigned char pre_pd_exit_mclk;
+	/* Precharge powerdown exit timing (tAXPD). */
+	unsigned char taxpd_mclk;
+	/* Mode register set cycle time (tMRD). */
+	unsigned char tmrd_mclk;
+
+	/* (tXARD and tXARDS). Empirical? */
+	act_pd_exit_mclk = 2;
+
+	/* XXX:  tXARD = 2, tXARDS = 7 - AL. * Empirical? */
+	pre_pd_exit_mclk = 6;
+
+	/*
+	 * FIXME:  tXP = 2 on Micron 667 MHz DIMM
+	 * FIXME: configurable?
+	 */
+	taxpd_mclk = 8;
+
+	/* FIXME: configurable? */
+	tmrd_mclk = 2;
+
+	ddr->timing_cfg_0 = (0
+		| ((trwt_mclk & 0x3) << 30)	/* RWT */
+		| ((twrt_mclk & 0x3) << 28)	/* WRT */
+		| ((trrt_mclk & 0x3) << 26)	/* RRT */
+		| ((twwt_mclk & 0x3) << 24)	/* WWT */
+		| ((act_pd_exit_mclk & 0x7) << 20)  /* ACT_PD_EXIT */
+		| ((pre_pd_exit_mclk & 0x7) << 16)  /* PRE_PD_EXIT */
+		| ((taxpd_mclk & 0xf) << 8)	/* ODT_PD_EXIT */
+		| ((tmrd_mclk & 0xf) << 0)	/* MRS_CYC */
+		);
+	debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+}
+#endif	/* defined(CONFIG_FSL_DDR2) */
+
+/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
+static void set_timing_cfg_3(fsl_memctl_config_regs_t *ddr,
+			       const common_timing_params_t *common_dimm)
+{
+	/* Extended Activate to precharge interval (tRAS) */
+	unsigned int ext_acttopre = 0;
+	unsigned int ext_refrec; /* Extended refresh recovery time (tRFC) */
+	unsigned int ext_caslat = 0; /* Extended MCAS latency from READ cmd */
+	unsigned int cntl_adj = 0; /* Control Adjust */
+
+	ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4;
+	ddr->timing_cfg_3 = (0
+		| ((ext_acttopre & 0x1) << 24)
+		| ((ext_refrec & 0x7) << 16)
+		| ((ext_caslat & 0x1) << 12)
+		| ((cntl_adj & 0x7) << 0)
+		);
+}
+
+/* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
+static void set_timing_cfg_1(fsl_memctl_config_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency)
+{
+	/* Precharge-to-activate interval (tRP) */
+	unsigned char pretoact_mclk;
+	/* Activate to precharge interval (tRAS) */
+	unsigned char acttopre_mclk;
+	/*  Activate to read/write interval (tRCD) */
+	unsigned char acttorw_mclk;
+	/* CASLAT */
+	unsigned char caslat_ctrl;
+	/*  Refresh recovery time (tRFC) ; trfc_low */
+	unsigned char refrec_ctrl;
+	/* Last data to precharge minimum interval (tWR) */
+	unsigned char wrrec_mclk;
+	/* Activate-to-activate interval (tRRD) */
+	unsigned char acttoact_mclk;
+	/* Last write data pair to read command issue interval (tWTR) */
+	unsigned char wrtord_mclk;
+
+	pretoact_mclk = picos_to_mclk(common_dimm->tRP_ps);
+	acttopre_mclk = picos_to_mclk(common_dimm->tRAS_ps);
+	acttorw_mclk = picos_to_mclk(common_dimm->tRCD_ps);
+
+	/*
+	 * Translate CAS Latency to a DDR controller field value:
+	 *
+	 *      CAS Lat DDR I   DDR II  Ctrl
+	 *      Clocks  SPD Bit SPD Bit Value
+	 *      ------- ------- ------- -----
+	 *      1.0     0               0001
+	 *      1.5     1               0010
+	 *      2.0     2       2       0011
+	 *      2.5     3               0100
+	 *      3.0     4       3       0101
+	 *      3.5     5               0110
+	 *      4.0             4       0111
+	 *      4.5                     1000
+	 *      5.0             5       1001
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	caslat_ctrl = (cas_latency + 1) & 0x07;
+#elif defined(CONFIG_FSL_DDR2)
+	caslat_ctrl = 2 * cas_latency - 1;
+#else
+#error "Need CAS Latency help for DDR3 in fsl_ddr_sdram.c"
+#endif
+
+	refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8;
+	wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps);
+	acttoact_mclk = picos_to_mclk(common_dimm->tRRD_ps);
+	wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps);
+
+	ddr->timing_cfg_1 = (0
+		| ((pretoact_mclk & 0x07) << 28)
+		| ((acttopre_mclk & 0x0F) << 24)
+		| ((acttorw_mclk & 0x7) << 20)
+		| ((caslat_ctrl & 0xF) << 16)
+		| ((refrec_ctrl & 0xF) << 12)
+		| ((wrrec_mclk & 0x07) << 8)
+		| ((acttoact_mclk & 0x07) << 4)
+		| ((wrtord_mclk & 0x07) << 0)
+		);
+}
+
+/* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
+static void set_timing_cfg_2(fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	/* Additive latency */
+	unsigned char add_lat_mclk;
+	/* CAS-to-preamble override */
+	unsigned short cpo;
+	/* Write latency */
+	unsigned char wr_lat;
+	/*  Read to precharge (tRTP) */
+	unsigned char rd_to_pre;
+	/* Write command to write data strobe timing adjustment */
+	unsigned char wr_data_delay;
+	/* Minimum CKE pulse width (tCKE) */
+	unsigned char cke_pls;
+	/* Window for four activates (tFAW) */
+	unsigned short four_act;
+
+	/* FIXME add check that this must be less than acttorw_mclk */
+	add_lat_mclk = additive_latency;
+	cpo = popts->cpo_override;
+
+#if defined(CONFIG_FSL_DDR1)
+	/*
+	 * This is a lie.  It should really be 1, but if it is
+	 * set to 1, bits overlap into the old controller's
+	 * otherwise unused ACSM field.  If we leave it 0, then
+	 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
+	 */
+	wr_lat = 0;
+#elif defined(CONFIG_FSL_DDR2)
+	wr_lat = cas_latency + additive_latency - 1;
+#else
+#error "Fix WR_LAT for DDR3"
+#endif
+
+	rd_to_pre = picos_to_mclk(common_dimm->tRTP_ps);
+	wr_data_delay = popts->write_data_delay;
+	cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
+	four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps);
+
+	ddr->timing_cfg_2 = (0
+		| ((add_lat_mclk & 0x7) << 28)
+		| ((cpo & 0x1f) << 23)
+		| ((wr_lat & 0x7) << 19)
+		| ((rd_to_pre & 0x7) << 13)
+		| ((wr_data_delay & 0x7) << 10)
+		| ((cke_pls & 0x7) << 6)
+		| ((four_act & 0x1f) << 0)
+		);
+}
+
+/* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
+static void set_ddr_sdram_cfg(fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm)
+{
+	unsigned int mem_en;		/* DDR SDRAM interface logic enable */
+	unsigned int sren;		/* Self refresh enable (during sleep) */
+	unsigned int ecc_en;		/* ECC enable. */
+	unsigned int rd_en;		/* Registered DIMM enable */
+	unsigned int sdram_type;	/* Type of SDRAM */
+	unsigned int dyn_pwr;		/* Dynamic power management mode */
+	unsigned int dbw;		/* DRAM dta bus width */
+	unsigned int eight_be;		/* 8-beat burst enable */
+	unsigned int ncap = 0;		/* Non-concurrent auto-precharge */
+	unsigned int threeT_en;		/* Enable 3T timing */
+	unsigned int twoT_en;		/* Enable 2T timing */
+	unsigned int ba_intlv_ctl;	/* Bank (CS) interleaving control */
+	unsigned int x32_en = 0;	/* x32 enable */
+	unsigned int pchb8 = 0;		/* precharge bit 8 enable */
+	unsigned int hse;		/* Global half strength override */
+	unsigned int mem_halt = 0;	/* memory controller halt */
+	unsigned int bi = 0;		/* Bypass initialization */
+
+	mem_en = 1;
+	sren = popts->self_refresh_in_sleep;
+	if (common_dimm->all_DIMMs_ECC_capable) {
+		/* Allow setting of ECC only if all DIMMs are ECC. */
+		ecc_en = popts->ECC_mode;
+	} else {
+		ecc_en = 0;
+	}
+
+	rd_en = (common_dimm->all_DIMMs_registered
+		 && !common_dimm->all_DIMMs_unbuffered);
+
+	sdram_type = fsl_ddr_type_function();
+
+	dyn_pwr = popts->dynamic_power;
+	dbw = popts->data_bus_width;
+	eight_be = 0;		/* always 0 for DDR2 */
+	threeT_en = 0;		/* FIXME: make this configurable */
+	twoT_en = popts->twoT_en;
+	ba_intlv_ctl = popts->ba_intlv_ctl;
+	hse = popts->half_strength_driver_enable;
+
+	ddr->ddr_sdram_cfg = (0
+			| ((mem_en & 0x1) << 31)
+			| ((sren & 0x1) << 30)
+			| ((ecc_en & 0x1) << 29)
+			| ((rd_en & 0x1) << 28)
+			| ((sdram_type & 0x7) << 24)
+			| ((dyn_pwr & 0x1) << 21)
+			| ((dbw & 0x3) << 19)
+			| ((eight_be & 0x1) << 18)
+			| ((ncap & 0x1) << 17)
+			| ((threeT_en & 0x1) << 16)
+			| ((twoT_en & 0x1) << 15)
+			| ((ba_intlv_ctl & 0x7F) << 8)
+			| ((x32_en & 0x1) << 5)
+			| ((pchb8 & 0x1) << 4)
+			| ((hse & 0x1) << 3)
+			| ((mem_halt & 0x1) << 1)
+			| ((bi & 0x1) << 0)
+			);
+}
+
+/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
+static void set_ddr_sdram_cfg_2(fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts)
+{
+	unsigned int frc_sr = 0;	/* Force self refresh */
+	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
+	unsigned int dll_rst_dis;	/* DLL reset disable */
+	unsigned int dqs_cfg;		/* DQS configuration */
+	unsigned int odt_cfg;		/* ODT configuration */
+	unsigned int num_pr;		/* Number of posted refreshes */
+	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
+	unsigned int ap_en;		/* Address Parity Enable */
+	unsigned int d_init;		/* DRAM data initialization */
+	unsigned int rcw_en = 0;	/* Register Control Word Enable */
+	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
+
+	dll_rst_dis = 1;	/* Make this configurable */
+	dqs_cfg = popts->DQS_config;
+	if (popts->cs_local_opts[0].odt_rd_cfg
+	    || popts->cs_local_opts[0].odt_wr_cfg) {
+		/* FIXME */
+		odt_cfg = 2;
+	} else {
+		odt_cfg = 0;
+	}
+
+	num_pr = 1;	/* Make this configurable */
+
+	/*
+	 * 8572 manual says
+	 *     {TIMING_CFG_1[PRETOACT]
+	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
+	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
+	 *      << DDR_SDRAM_INTERVAL[REFINT]
+	 */
+
+	obc_cfg = 0;	/* Make this configurable? */
+	ap_en = 0;	/* Make this configurable? */
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+	/* Use the DDR controller to auto initialize memory. */
+	d_init = 1;
+	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
+	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
+#else
+	/* Memory will be initialized via DMA, or not at all. */
+	d_init = 0;
+#endif
+
+	ddr->ddr_sdram_cfg_2 = (0
+		| ((frc_sr & 0x1) << 31)
+		| ((sr_ie & 0x1) << 30)
+		| ((dll_rst_dis & 0x1) << 29)
+		| ((dqs_cfg & 0x3) << 26)
+		| ((odt_cfg & 0x3) << 21)
+		| ((num_pr & 0xf) << 12)
+		| ((obc_cfg & 0x1) << 6)
+		| ((ap_en & 0x1) << 5)
+		| ((d_init & 0x1) << 4)
+		| ((rcw_en & 0x1) << 2)
+		| ((md_en & 0x1) << 0)
+		);
+}
+
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
+
+	ddr->ddr_sdram_mode_2 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+}
+
+/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
+static void set_ddr_sdram_interval(fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm)
+{
+	unsigned int refint;	/* Refresh interval */
+	unsigned int bstopre;	/* Precharge interval */
+
+	refint = picos_to_mclk(common_dimm->refresh_rate_ps);
+
+	bstopre = popts->bstopre;
+
+	/* FIXME: refint field used 0x3FFF in earlier controllers */
+	ddr->ddr_sdram_interval = (0
+				   | ((refint & 0xFFFF) << 16)
+				   | ((bstopre & 0x3FFF) << 0)
+				   );
+}
+
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_memctl_config_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	unsigned short esdmode;		/* Extended SDRAM mode */
+	unsigned short sdmode;		/* SDRAM mode */
+
+	/*
+	 * FIXME: This ought to be pre-calculated in a
+	 * technology-specific routine,
+	 * e.g. compute_DDR2_mode_register(), and then the
+	 * sdmode and esdmode passed in as part of common_dimm.
+	 */
+
+	/* Extended Mode Register */
+	unsigned int mrs = 0;		/* Mode Register Set */
+	unsigned int outputs = 0;	/* 0=Enabled, 1=Disabled */
+	unsigned int rdqs_en = 0;	/* RDQS Enable: 0=no, 1=yes */
+	unsigned int dqs_en = 0;	/* DQS# Enable: 0=enable, 1=disable */
+	unsigned int ocd = 0;		/* 0x0=OCD not supported,
+					   0x7=OCD default state */
+	unsigned int rtt;
+	unsigned int al;		/* Posted CAS# additive latency (AL) */
+	unsigned int ods = 0;		/* Output Drive Strength:
+						0 = Full strength (18ohm)
+						1 = Reduced strength (4ohm) */
+	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
+						       1=Disable (Test/Debug) */
+
+	/* Mode Register (MR) */
+	unsigned int mr;	/* Mode Register Definition */
+	unsigned int pd;	/* Power-Down Mode */
+	unsigned int wr;	/* Write Recovery */
+	unsigned int dll_res;	/* DLL Reset */
+	unsigned int mode;	/* Normal=0 or Test=1 */
+	unsigned int caslat;	/* CAS# latency */
+	/* BT: Burst Type (0=Sequential, 1=Interleaved) */
+	unsigned int bt;
+	unsigned int bl;	/* BL: Burst Length */
+
+#if defined(CONFIG_FSL_DDR2)
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+#endif
+
+	rtt = fsl_ddr_get_rtt();
+
+	al = additive_latency;
+
+	esdmode = (0
+		| ((mrs & 0x3) << 14)
+		| ((outputs & 0x1) << 12)
+		| ((rdqs_en & 0x1) << 11)
+		| ((dqs_en & 0x1) << 10)
+		| ((ocd & 0x7) << 7)
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((al & 0x7) << 3)
+		| ((rtt & 0x1) << 2)   /* rtt field is split */
+		| ((ods & 0x1) << 1)
+		| ((dll_en & 0x1) << 0)
+		);
+
+	mr = 0;		 /* FIXME: CHECKME */
+
+	/*
+	 * 0 = Fast Exit (Normal)
+	 * 1 = Slow Exit (Low Power)
+	 * FIXME: make this configurable
+	 */
+	pd = 0;
+
+#if defined(CONFIG_FSL_DDR1)
+	wr = 0;       /* Historical */
+#elif defined(CONFIG_FSL_DDR2)
+	wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1;
+#else
+#error "Write tWR_auto for DDR3"
+#endif
+	dll_res = 0;	/* FIXME: make this configurable */
+	mode = 0;	/* FIXME: make this configurable */
+
+#if defined(CONFIG_FSL_DDR1)
+	if (1 <= cas_latency && cas_latency <= 4) {
+		unsigned char mode_caslat_table[4] = {
+			0x5,	/* 1.5 clocks */
+			0x2,	/* 2.0 clocks */
+			0x6,	/* 2.5 clocks */
+			0x3	/* 3.0 clocks */
+		};
+	caslat = mode_caslat_table[cas_latency - 1];
+	}
+#elif defined(CONFIG_FSL_DDR2)
+	caslat = cas_latency;
+#else
+#error "Fix the mode CAS Latency for DDR3"
+#endif
+	bt = 0;		/* FIXME: make this configurable? */
+
+	switch (popts->burst_length) {
+	case 4:
+		bl = 2;
+		break;
+	case 8:
+		bl = 3;
+		break;
+	default:
+		printf("Error: invalid burst length of %u specified. "
+			" Defaulting to 4 beats.\n",
+			popts->burst_length);
+		bl = 2;
+		break;
+	}
+
+	sdmode = (0
+		  | ((mr & 0x3) << 14)
+		  | ((pd & 0x1) << 12)
+		  | ((wr & 0x7) << 9)
+		  | ((dll_res & 0x1) << 8)
+		  | ((mode & 0x1) << 7)
+		  | ((caslat & 0x7) << 4)
+		  | ((bt & 0x1) << 3)
+		  | ((bl & 0x7) << 0)
+		  );
+
+	ddr->ddr_sdram_mode = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+}
+
+
+/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
+static void set_ddr_data_init(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int init_value;	/* Initialization value */
+
+	init_value = 0xDEADBEEF;	/* FIXME: should be configurable */
+	ddr->ddr_data_init = init_value;
+}
+
+/*
+ * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
+ * The old controller on the 8540/60 doesn't have this register.
+ * Hope it's OK to set it (to 0) anyway.
+ */
+static void set_ddr_sdram_clk_cntl(fsl_memctl_config_regs_t *ddr,
+					 const memctl_options_t *popts)
+{
+	unsigned int clk_adjust;	/* Clock adjust */
+
+	clk_adjust = popts->clk_adjust;
+	ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23;
+}
+
+/* DDR Initialization Address (DDR_INIT_ADDR) */
+static void set_ddr_init_addr(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int init_addr = 0;	/* Initialization address */
+
+	ddr->ddr_init_addr = init_addr;
+}
+
+/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
+static void set_ddr_init_ext_addr(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int uia = 0;	/* Use initialization address */
+	unsigned int init_ext_addr = 0;	/* Initialization address */
+
+	ddr->ddr_init_ext_addr = (0
+				  | ((uia & 0x1) << 31)
+				  | (init_ext_addr & 0xF)
+				  );
+}
+
+/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
+static void set_timing_cfg_4(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
+	unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
+	unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
+	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
+	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
+
+	ddr->timing_cfg_4 = (0
+			     | ((rwt & 0xf) << 28)
+			     | ((wrt & 0xf) << 24)
+			     | ((rrt & 0xf) << 20)
+			     | ((wwt & 0xf) << 16)
+			     | (dll_lock & 0x3)
+			     );
+}
+
+/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
+static void set_timing_cfg_5(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int rodt_on = 0;	/* Read to ODT on */
+	unsigned int rodt_off = 0;	/* Read to ODT off */
+	unsigned int wodt_on = 0;	/* Write to ODT on */
+	unsigned int wodt_off = 0;	/* Write to ODT off */
+
+	ddr->timing_cfg_5 = (0
+			     | ((rodt_on & 0xf) << 24)
+			     | ((rodt_off & 0xf) << 20)
+			     | ((wodt_on & 0xf) << 12)
+			     | ((wodt_off & 0xf) << 8)
+			     );
+}
+
+/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
+static void set_ddr_zq_cntl(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int zq_en = 0;	/* ZQ Calibration Enable */
+	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
+	/* Normal Operation Full Calibration Time (tZQoper) */
+	unsigned int zqoper = 0;
+	/* Normal Operation Short Calibration Time (tZQCS) */
+	unsigned int zqcs = 0;
+
+	ddr->ddr_zq_cntl = (0
+			    | ((zq_en & 0x1) << 31)
+			    | ((zqinit & 0xF) << 24)
+			    | ((zqoper & 0xF) << 16)
+			    | ((zqcs & 0xF) << 8)
+			    );
+}
+
+/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
+static void set_ddr_wrlvl_cntl(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int wrlvl_en = 0; /* Write Leveling Enable */
+	/*
+	 * First DQS pulse rising edge after margining mode
+	 * is programmed (tWL_MRD)
+	 */
+	unsigned int wrlvl_mrd = 0;
+	/* ODT delay after margining mode is programmed (tWL_ODTEN) */
+	unsigned int wrlvl_odten = 0;
+	/* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
+	unsigned int wrlvl_dqsen = 0;
+	/* WRLVL_SMPL: Write leveling sample time */
+	unsigned int wrlvl_smpl = 0;
+	/* WRLVL_WLR: Write leveling repeition time */
+	unsigned int wrlvl_wlr = 0;
+	/* WRLVL_START: Write leveling start time */
+	unsigned int wrlvl_start = 0;
+
+	ddr->ddr_wrlvl_cntl = (0
+			       | ((wrlvl_en & 0x1) << 31)
+			       | ((wrlvl_mrd & 0x7) << 24)
+			       | ((wrlvl_odten & 0x7) << 20)
+			       | ((wrlvl_dqsen & 0x7) << 16)
+			       | ((wrlvl_smpl & 0xf) << 12)
+			       | ((wrlvl_wlr & 0x7) << 8)
+			       | ((wrlvl_start & 0xF) << 0)
+			       );
+}
+
+/* DDR Self Refresh Counter (DDR_SR_CNTR) */
+static void set_ddr_sr_cntr(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int sr_it = 0;	/* Self Refresh Idle Threshold */
+
+	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
+}
+
+/* DDR Pre-Drive Conditioning Control (DDR_PD_CNTL) */
+static void set_ddr_pd_cntl(fsl_memctl_config_regs_t *ddr)
+{
+	/* Termination value during pre-drive conditioning */
+	unsigned int tvpd = 0;
+	unsigned int pd_en = 0;		/* Pre-Drive Conditioning Enable */
+	unsigned int pdar = 0;		/* Pre-Drive After Read */
+	unsigned int pdaw = 0;		/* Pre-Drive After Write */
+	unsigned int pd_on = 0;		/* Pre-Drive Conditioning On */
+	unsigned int pd_off = 0;	/* Pre-Drive Conditioning Off */
+
+	ddr->ddr_pd_cntl = (0
+			    | ((pd_en & 0x1) << 31)
+			    | ((tvpd & 0x7) << 28)
+			    | ((pdar & 0x7F) << 20)
+			    | ((pdaw & 0x7F) << 12)
+			    | ((pd_on & 0x1F) << 6)
+			    | ((pd_off & 0x1F) << 0)
+			    );
+}
+
+
+/* DDR SDRAM Register Control Word 1 (DDR_SDRAM_RCW_1) */
+static void set_ddr_sdram_rcw_1(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int rcw0 = 0;	/* RCW0: Register Control Word 0 */
+	unsigned int rcw1 = 0;	/* RCW1: Register Control Word 1 */
+	unsigned int rcw2 = 0;	/* RCW2: Register Control Word 2 */
+	unsigned int rcw3 = 0;	/* RCW3: Register Control Word 3 */
+	unsigned int rcw4 = 0;	/* RCW4: Register Control Word 4 */
+	unsigned int rcw5 = 0;	/* RCW5: Register Control Word 5 */
+	unsigned int rcw6 = 0;	/* RCW6: Register Control Word 6 */
+	unsigned int rcw7 = 0;	/* RCW7: Register Control Word 7 */
+
+	ddr->ddr_sdram_rcw_1 = (0
+				| ((rcw0 & 0xF) << 28)
+				| ((rcw1 & 0xF) << 24)
+				| ((rcw2 & 0xF) << 20)
+				| ((rcw3 & 0xF) << 16)
+				| ((rcw4 & 0xF) << 12)
+				| ((rcw5 & 0xF) << 8)
+				| ((rcw6 & 0xF) << 4)
+				| ((rcw7 & 0xF) << 0)
+				);
+}
+
+/* DDR SDRAM Register Control Word 2 (DDR_SDRAM_RCW_2) */
+static void set_ddr_sdram_rcw_2(fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int rcw8 = 0;	/* RCW0: Register Control Word 8 */
+	unsigned int rcw9 = 0;	/* RCW1: Register Control Word 9 */
+	unsigned int rcw10 = 0;	/* RCW2: Register Control Word 10 */
+	unsigned int rcw11 = 0;	/* RCW3: Register Control Word 11 */
+	unsigned int rcw12 = 0;	/* RCW4: Register Control Word 12 */
+	unsigned int rcw13 = 0;	/* RCW5: Register Control Word 13 */
+	unsigned int rcw14 = 0;	/* RCW6: Register Control Word 14 */
+	unsigned int rcw15 = 0;	/* RCW7: Register Control Word 15 */
+
+	ddr->ddr_sdram_rcw_2 = (0
+				| ((rcw8 & 0xF) << 28)
+				| ((rcw9 & 0xF) << 24)
+				| ((rcw10 & 0xF) << 20)
+				| ((rcw11 & 0xF) << 16)
+				| ((rcw12 & 0xF) << 12)
+				| ((rcw13 & 0xF) << 8)
+				| ((rcw14 & 0xF) << 4)
+				| ((rcw15 & 0xF) << 0)
+				);
+}
+
+unsigned int
+check_fsl_memctl_config_regs(const fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int res = 0;
+
+	/*
+	 * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
+	 * not set@the same time.
+	 */
+	if (ddr->ddr_sdram_cfg & 0x10000000
+	    && ddr->ddr_sdram_cfg & 0x00008000) {
+		printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
+				" should not be set at the same time.\n");
+		res++;
+	}
+
+	return res;
+}
+
+unsigned int
+compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+			       fsl_memctl_config_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       const dimm_params_t *dimm_params,
+			       unsigned int dbw_cap_adj)
+{
+	unsigned int i;
+	unsigned int cas_latency;
+	unsigned int additive_latency;
+
+	memset(ddr, 0, sizeof(fsl_memctl_config_regs_t));
+
+	if (common_dimm == NULL) {
+		printf("Error: subset DIMM params struct null pointer\n");
+		return 1;
+	}
+
+	/*
+	 * Process overrides first.
+	 *
+	 * FIXME: somehow add dereated caslat to this
+	 */
+	cas_latency = (popts->cas_latency_override)
+		? popts->cas_latency_override_value
+		: common_dimm->lowest_common_SPD_caslat;
+
+	additive_latency = (popts->additive_latency_override)
+		? popts->additive_latency_override_value
+		: common_dimm->additive_latency;
+
+	/* Chip Select Memory Bounds (CSn_BNDS) */
+	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 */
+			break;
+		}
+
+		if (dimm_params[i/2].n_ranks == 0) {
+			debug("Skipping setup of CS%u "
+				"because n_ranks on DIMM %u is 0\n", i, i/2);
+			continue;
+		}
+		if (popts->memctl_interleaving && popts->ba_intlv_ctl) {
+			/*
+			 * This works superbank 2CS
+			 * There are 2 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.
+			 */
+			ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1;
+		}
+		else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {
+			/*
+			 * If memory interleaving between controllers is NOT
+			 * enabled, the starting address for each memory
+			 * controller is distinct.  However, because rank
+			 * interleaving is enabled, the starting and ending
+			 * addresses of the total memory on that memory
+			 * 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;
+		}
+		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) {
+				unsigned long long rank_density
+						= dimm_params[0].rank_density;
+				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.
+			 */
+			unsigned long long rank_density
+						= dimm_params[i/2].rank_density;
+			sa = dimm_params[i/2].base_address;
+			ea = sa + (rank_density >> dbw_cap_adj) - 1;
+			if (i&1) {
+				if ((dimm_params[i/2].n_ranks == 1)) {
+					/* Odd chip select, single-rank dimm */
+					sa = 0;
+					ea = 0;
+				} else {
+					/* Odd chip select, dual-rank DIMM */
+					sa += rank_density >> dbw_cap_adj;
+					ea += rank_density >> dbw_cap_adj;
+				}
+			}
+		}
+
+		sa >>= 24;
+		ea >>= 24;
+
+		/*
+		 * FIXME: 32-bit physical ram versions use 2 nibbles
+		 * FIXME: 36-bit physical ram versions use 3 nibbles
+		 */
+		ddr->cs[i].bnds = (0
+			| ((sa & 0xFFF) << 16)	/* starting address MSB */
+			| ((ea & 0xFFF) << 0)	/* ending address MSB */
+			);
+
+		set_csn_config(i, ddr, popts, dimm_params);
+		set_csn_config_2(i, ddr);
+	}
+
+#if defined(CONFIG_FSL_DDR2)
+	set_timing_cfg_0(ddr);
+#endif
+
+	set_timing_cfg_3(ddr, common_dimm);
+	set_timing_cfg_1(ddr, common_dimm, cas_latency);
+	set_timing_cfg_2(ddr, popts, common_dimm,
+				cas_latency, additive_latency);
+
+	set_ddr_sdram_cfg(ddr, popts, common_dimm);
+
+	set_ddr_sdram_cfg_2(ddr, popts);
+	set_ddr_sdram_mode(ddr, popts, common_dimm,
+				cas_latency, additive_latency);
+	set_ddr_sdram_mode_2(ddr);
+	set_ddr_sdram_interval(ddr, popts, common_dimm);
+	set_ddr_data_init(ddr);
+	set_ddr_sdram_clk_cntl(ddr, popts);
+	set_ddr_init_addr(ddr);
+	set_ddr_init_ext_addr(ddr);
+	set_timing_cfg_4(ddr);
+	set_timing_cfg_5(ddr);
+
+	set_ddr_zq_cntl(ddr);
+	set_ddr_wrlvl_cntl(ddr);
+
+	set_ddr_pd_cntl(ddr);
+	set_ddr_sr_cntr(ddr);
+
+	set_ddr_sdram_rcw_1(ddr);
+	set_ddr_sdram_rcw_2(ddr);
+
+	return check_fsl_memctl_config_regs(ddr);
+}
diff --git a/cpu/mpc8xxx/fsl_ddr_sdram.c b/cpu/mpc8xxx/fsl_ddr_sdram.c
new file mode 100644
index 0000000..0663609
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr_sdram.c
@@ -0,0 +1,1134 @@
+/*
+ * 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+
+#include "fsl_ddr_sdram.h"
+
+/* Board-specific functions defined in each board's ddr.c */
+void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+			   unsigned int ctrl_num);
+void fsl_ddr_dump_memctl_regs(unsigned int ctrl_num);
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+				   unsigned int ctrl_num);
+void fsl_ddr_set_lawbar(
+		const common_timing_params_t *memctl_common_params,
+		unsigned int memctl_interleaved,
+		unsigned int ctrl_num);
+unsigned int fsl_ddr_type_function(void);
+unsigned int fsl_ddr_clk_adjust_function(void);
+unsigned int fsl_ddr_cpo_override_function(void);
+unsigned int fsl_ddr_write_data_delay_function(void);
+unsigned int fsl_ddr_half_strength_driver_enable_function(void);
+
+extern unsigned int
+compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+			       fsl_memctl_config_regs_t *ddr,
+			       const common_timing_params_t *common_dimm,
+			       const dimm_params_t *dimm_parameters,
+			       unsigned int dbw_capacity_adjust);
+
+/*
+ * ASSUMPTIONS:
+ *    - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller
+ *    - Same memory data bus width on all controllers
+ *
+ * NOTES:
+ *
+ * The memory controller and associated documentation use confusing
+ * terminology when referring to the orgranization of DRAM.
+ *
+ * Here is a terminology translation table:
+ *
+ * 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
+ *
+ * The naming confusion is further exacerbated by the descriptions of the
+ * memory controller interleaving feature, where accesses are interleaved
+ * _BETWEEN_ two seperate memory controllers.  This is configured only in
+ * CS0_CONFIG[INTLV_CTL] of each memory controller.
+ *
+ * memory controller documentation | number of chip selects
+ *                                 | 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
+ *
+ * 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
+ * -----------------------------|-----------------------|------------------
+ * DDR_SDRAM_CFG[BA_INTLV_CTL]  | Bank (chip select)    | rank interleaving
+ *                              |  interleaving
+ */
+
+#ifdef DEBUG
+const char *step_string_tbl[] = {
+	"STEP_GET_SPD",
+	"STEP_COMPUTE_DIMM_PARMS",
+	"STEP_COMPUTE_COMMON_PARMS",
+	"STEP_GATHER_OPTS",
+	"STEP_ASSIGN_ADDRESSES",
+	"STEP_COMPUTE_REGS",
+	"STEP_PROGRAM_REGS",
+	"STEP_ALL"	/* FIXME: probably shouldn't be here */
+};
+
+const char * step_to_string(unsigned int step) {
+	return step_string_tbl[step];
+}
+#endif
+
+/*
+ * compute_lowest_common_dimm_parameters()
+ *
+ * Determine the worst-case DIMM timing parameters from the set of DIMMs
+ * whose parameters have been computed into the array pointed to
+ * by dimm_params.
+ */
+static unsigned int
+compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
+				      common_timing_params_t *outpdimm,
+				      unsigned int number_of_dimms)
+{
+	unsigned int i;
+
+	unsigned int tCKmin_X_ps = 0;
+	unsigned int tCKmax_ps = 0xFFFFFFFF;
+	unsigned int tCKmax_max_ps = 0;
+	unsigned int tRCD_ps = 0;
+	unsigned int tRP_ps = 0;
+	unsigned int tRAS_ps = 0;
+	unsigned int tWR_ps = 0;
+	unsigned int tWTR_ps = 0;
+	unsigned int tRFC_ps = 0;
+	unsigned int tRRD_ps = 0;
+	unsigned int tRC_ps = 0;
+	unsigned int refresh_rate_ps = 0;
+	unsigned int tIS_ps = 0;
+	unsigned int tIH_ps = 0;
+	unsigned int tDS_ps = 0;
+	unsigned int tDH_ps = 0;
+	unsigned int tRTP_ps = 0;
+	unsigned int tDQSQ_max_ps = 0;
+	unsigned int tQHS_ps = 0;
+
+	unsigned int temp1, temp2;
+	unsigned int lowest_good_caslat;
+	unsigned int additive_latency = 0;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+	unsigned int not_ok;
+
+	debug("using mclk_ps = %u\n", mclk_ps);
+
+	temp1 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		/*
+		 * If there are no ranks on this DIMM,
+		 * it probably doesn't exist, so skip it.
+		 */
+		if (dimm_params[i].n_ranks == 0) {
+			temp1++;
+			continue;
+		}
+
+		/*
+		 * Find minimum tCKmax_ps to find fastest slow speed,
+		 * i.e., this is the slowest the whole system can go.
+		 */
+		tCKmax_ps = min(tCKmax_ps, dimm_params[i].tCKmax_ps);
+
+		/* Either find maximum value to determine slowest
+		 * speed, delay, time, period, etc */
+		tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+		tCKmax_max_ps = max(tCKmax_max_ps, dimm_params[i].tCKmax_ps);
+		tRCD_ps = max(tRCD_ps, dimm_params[i].tRCD_ps);
+		tRP_ps = max(tRP_ps, dimm_params[i].tRP_ps);
+		tRAS_ps = max(tRAS_ps, dimm_params[i].tRAS_ps);
+		tWR_ps = max(tWR_ps, dimm_params[i].tWR_ps);
+		tWTR_ps = max(tWTR_ps, dimm_params[i].tWTR_ps);
+		tRFC_ps = max(tRFC_ps, dimm_params[i].tRFC_ps);
+		tRRD_ps = max(tRRD_ps, dimm_params[i].tRRD_ps);
+		tRC_ps = max(tRC_ps, dimm_params[i].tRC_ps);
+		tIS_ps = max(tIS_ps, dimm_params[i].tIS_ps);
+		tIH_ps = max(tIH_ps, dimm_params[i].tIH_ps);
+		tDS_ps = max(tDS_ps, dimm_params[i].tDS_ps);
+		tDH_ps = max(tDH_ps, dimm_params[i].tDH_ps);
+		tRTP_ps = max(tRTP_ps, dimm_params[i].tRTP_ps);
+		tQHS_ps = max(tQHS_ps, dimm_params[i].tQHS_ps);
+		refresh_rate_ps = max(refresh_rate_ps,
+				      dimm_params[i].refresh_rate_ps);
+
+		/*
+		 * Find maximum tDQSQ_max_ps to find slowest.
+		 *
+		 * FIXME: is finding the slowest value the correct
+		 * strategy for this parameter?
+		 */
+		tDQSQ_max_ps = max(tDQSQ_max_ps, dimm_params[i].tDQSQ_max_ps);
+	}
+
+	outpdimm->ndimms_present = number_of_dimms - temp1;
+
+	if (temp1 == number_of_dimms) {
+		debug("no dimms this memory controller\n");
+		return 0;
+	}
+
+	outpdimm->tCKmin_X_ps = tCKmin_X_ps;
+	outpdimm->tCKmax_ps = tCKmax_ps;
+	outpdimm->tCKmax_max_ps = tCKmax_max_ps;
+	outpdimm->tRCD_ps = tRCD_ps;
+	outpdimm->tRP_ps = tRP_ps;
+	outpdimm->tRAS_ps = tRAS_ps;
+	outpdimm->tWR_ps = tWR_ps;
+	outpdimm->tWTR_ps = tWTR_ps;
+	outpdimm->tRFC_ps = tRFC_ps;
+	outpdimm->tRRD_ps = tRRD_ps;
+	outpdimm->tRC_ps = tRC_ps;
+	outpdimm->refresh_rate_ps = refresh_rate_ps;
+	outpdimm->tIS_ps = tIS_ps;
+	outpdimm->tIH_ps = tIH_ps;
+	outpdimm->tDS_ps = tDS_ps;
+	outpdimm->tDH_ps = tDH_ps;
+	outpdimm->tRTP_ps = tRTP_ps;
+	outpdimm->tDQSQ_max_ps = tDQSQ_max_ps;
+	outpdimm->tQHS_ps = tQHS_ps;
+
+	/* Determine common burst length for all DIMMs. */
+	temp1 = 0xff;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			temp1 &= dimm_params[i].burst_lengths_bitmask;
+		}
+	}
+	outpdimm->all_DIMMs_burst_lengths_bitmask = temp1;
+
+	/* Determine if all DIMMs registered buffered. */
+	temp1 = temp2 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			if (dimm_params[i].registered_dimm)
+				temp1 = 1;
+			if (!dimm_params[i].registered_dimm)
+				temp2 = 1;
+		}
+	}
+
+	outpdimm->all_DIMMs_registered = 0;
+	if (temp1 && !temp2) {
+		outpdimm->all_DIMMs_registered = 1;
+	}
+
+	outpdimm->all_DIMMs_unbuffered = 0;
+	if (!temp1 && temp2) {
+		outpdimm->all_DIMMs_unbuffered = 1;
+	}
+
+	/* CHECKME: */
+	if (!outpdimm->all_DIMMs_registered
+	    && !outpdimm->all_DIMMs_unbuffered) {
+		printf("ERROR:  Mix of registered buffered and unbuffered "
+				"DIMMs detected!\n");
+	}
+
+	/*
+	 * Compute a CAS latency suitable for all DIMMs
+	 *
+	 * Strategy for SPD-defined latencies: compute only
+	 * CAS latency defined by all DIMMs.
+	 */
+
+	/*
+	 * Step 1: find CAS latency common to all DIMMs using bitwise
+	 * operation.
+	 */
+	temp1 = 0xFF;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			temp2 = 0;
+			temp2 |= 1 << dimm_params[i].caslat_X;
+			temp2 |= 1 << dimm_params[i].caslat_X_minus_1;
+			temp2 |= 1 << dimm_params[i].caslat_X_minus_2;
+			/*
+			 * FIXME: If there was no entry for X-2 (X-1) in
+			 * the SPD, then caslat_X_minus_2
+			 * (caslat_X_minus_1) contains either 255 or
+			 * 0xFFFFFFFF because that's what the glorious
+			 * __ilog2 function returns for an input of 0.
+			 * On 32-bit PowerPC, left shift counts with bit
+			 * 26 set (that the value of 255 or 0xFFFFFFFF
+			 * will have), cause the destination register to
+			 * be 0.  That is why this works.
+			 */
+			temp1 &= temp2;
+		}
+	}
+
+	/*
+	 * Step 2: check each common CAS latency against tCK of each
+	 * DIMM's SPD.
+	 */
+	lowest_good_caslat = 0;
+	temp2 = 0;
+	while (temp1) {
+		not_ok = 0;
+		temp2 =  __ilog2(temp1);
+		debug("checking common caslat = %u\n", temp2);
+
+		/* Check if this CAS latency will work on all DIMMs@tCK. */
+		for (i = 0; i < number_of_dimms; i++) {
+			if (!dimm_params[i].n_ranks) {
+				continue;
+			}
+			if (dimm_params[i].caslat_X == temp2) {
+				if (mclk_ps >= dimm_params[i].tCKmin_X_ps) {
+					debug("CL = %u ok on DIMM %u at tCK=%u"
+					    " ps with its tCKmin_X_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       dimm_params[i].tCKmin_X_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_X_minus_1 == temp2) {
+				unsigned int tCKmin_X_minus_1_ps
+					= dimm_params[i].tCKmin_X_minus_1_ps;
+				if (mclk_ps >= tCKmin_X_minus_1_ps) {
+					debug("CL = %u ok on DIMM %u at "
+						"tCK=%u ps with its "
+						"tCKmin_X_minus_1_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       tCKmin_X_minus_1_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_X_minus_2 == temp2) {
+				unsigned int tCKmin_X_minus_2_ps
+					= dimm_params[i].tCKmin_X_minus_2_ps;
+				if (mclk_ps >= tCKmin_X_minus_2_ps) {
+					debug("CL = %u ok on DIMM %u at "
+						"tCK=%u ps with its "
+						"tCKmin_X_minus_2_ps of %u\n",
+					       temp2, i, mclk_ps,
+					       tCKmin_X_minus_2_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+		}
+
+		if (!not_ok) {
+			lowest_good_caslat = temp2;
+		}
+
+		temp1 &= ~(1 << temp2);
+	}
+
+	debug("lowest common SPD-defined CAS latency = %u\n",
+	       lowest_good_caslat);
+	outpdimm->lowest_common_SPD_caslat = lowest_good_caslat;
+
+
+	/*
+	 * Compute a common 'de-rated' CAS latency.
+	 *
+	 * The strategy here is to find the *highest* dereated cas latency
+	 * with the assumption that all of the DIMMs will support a dereated
+	 * CAS latency higher than or equal to their lowest dereated value.
+	 */
+	temp1 = 0;
+	for (i = 0; i < number_of_dimms; i++) {
+		temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
+	}
+	outpdimm->highest_common_derated_caslat = temp1;
+	debug("highest common dereated CAS latency = %u\n", temp1);
+
+	/* Determine if all DIMMs ECC capable. */
+	temp1 = 1;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks && dimm_params[i].edc_config != 2) {
+			temp1 = 0;
+			break;
+		}
+	}
+	if (temp1) {
+		debug("all DIMMs ECC capable\n");
+	} else {
+		debug("Warning: not all DIMMs ECC capable, cant enable ECC\n");
+	}
+	outpdimm->all_DIMMs_ECC_capable = temp1;
+
+
+	/* FIXME: move to somewhere else to validate. */
+	if (mclk_ps > tCKmax_max_ps) {
+		printf("Warning: some of the installed DIMMs "
+				"can not operate this slowly.\n");
+		return 1;
+	}
+
+	/*
+	 * Compute additive latency.
+	 *
+	 * For DDR1, additive latency should be 0.
+	 *
+	 * For DDR2, with ODT enabled, use "a value" less than ACTTORW,
+	 *	which comes from Trcd, and also note that:
+	 *	    add_lat + caslat must be >= 4
+	 *
+	 * For DDR3, FIXME additive latency determination
+	 *
+	 * When to use additive latency for DDR2:
+	 *
+	 * I. Because you are using CL=3 and need to do ODT on writes and
+	 *    want functionality.
+	 *    1. Are you going to use ODT? (Does your board not have
+	 *      additional termination circuitry for DQ, DQS, DQS_,
+	 *      DM, RDQS, RDQS_ for x4/x8 configs?)
+	 *    2. If so, is your lowest supported CL going to be 3?
+	 *    3. If so, then you must set AL=1 because
+	 *
+	 *       WL >= 3 for ODT on writes
+	 *       RL = AL + CL
+	 *       WL = RL - 1
+	 *       ->
+	 *       WL = AL + CL - 1
+	 *       AL + CL - 1 >= 3
+	 *       AL + CL >= 4
+	 *  QED
+	 *
+	 *  RL >= 3 for ODT on reads
+	 *  RL = AL + CL
+	 *
+	 *  Since CL aren't usually less than 2, AL=0 is a minimum,
+	 *  so the WL-derived AL should be the  -- FIXME?
+	 *
+	 * II. Because you are using auto-precharge globally and want to
+	 *     use additive latency (posted CAS) to get more bandwidth.
+	 *     1. Are you going to use auto-precharge mode globally?
+	 *
+	 *        Use addtivie latency and compute AL to be 1 cycle less than
+	 *        tRCD, i.e. the READ or WRITE command is in the cycle
+	 *        immediately following the ACTIVATE command..
+	 *
+	 * III. Because you feel like it or want to do some sort of
+	 *      degraded-performance experiment.
+	 *     1.  Do you just want to use additive latency because you feel
+	 *         like it?
+	 *
+	 * Validation:  AL is less than tRCD, and within the other
+	 * read-to-precharge constraints.
+	 */
+
+	additive_latency = 0;
+
+#if defined(CONFIG_FSL_DDR2)
+	if (lowest_good_caslat < 4) {
+		additive_latency = picos_to_mclk(tRCD_ps) - lowest_good_caslat;
+		if (mclk_to_picos(additive_latency) > tRCD_ps) {
+			additive_latency = picos_to_mclk(tRCD_ps);
+			debug("setting additive_latency to %u because it was "
+				" greater than tRCD_ps\n", additive_latency);
+		}
+	}
+
+#elif defined(CONFIG_FSL_DDR3)
+error "FIXME determine additive latency for DDR3"
+#endif
+
+	/*
+	 * Validate additive latency
+	 * FIXME: move to somewhere else to validate
+	 *
+	 * AL <= tRCD(min)
+	 */
+	if (mclk_to_picos(additive_latency) > tRCD_ps) {
+		printf("Error: invalid additive latency exceeds tRCD(min).\n");
+		return 1;
+	}
+
+	/*
+	 * FIXME: RL = CL + AL;  RL >= 3 for ODT_RD_CFG to be enabled
+	 * FIXME: WL = RL - 1;  WL >= 3 for ODT_WL_CFG to be enabled
+	 * FIXME: ADD_LAT (the register) must be set to a value less
+	 * FIXME: than ACTTORW if WL = 1, then AL must be set to 1
+	 * FIXME: RD_TO_PRE (the register) must be set to a minimum
+	 * FIXME: tRTP + AL if AL is nonzero
+	 */
+
+	/*
+	 * Additive latency will be applied only if the memctl option to
+	 * use it.
+	 */
+	outpdimm->additive_latency = additive_latency;
+
+	return 0;
+}
+
+/*
+ * Dummy function to init memctl options -- ultimately want an
+ * interactive version of this function
+ */
+unsigned int
+populate_memctl_options(const common_timing_params_t *pcommon_params,
+			memctl_options_t *popts,
+			unsigned int ctrl_num)
+{
+	unsigned int i;
+
+	/* Chip select options. */
+
+	/* Pick chip-select local options. */
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		/* If not DDR2, odt_rd_cfg and odt_wr_cfg need to be 0. */
+
+		/* only for single CS? */
+		popts->cs_local_opts[i].odt_rd_cfg = 0;
+
+		popts->cs_local_opts[i].odt_wr_cfg = 1;
+		popts->cs_local_opts[i].auto_precharge = 0;
+	}
+
+	/* Pick interleaving mode. */
+
+	/*
+	 * 0 = no interleaving
+	 * 1 = interleaving between 2 controllers
+	 */
+	popts->memctl_interleaving = 0;
+
+	/*
+	 * 0 = cacheline
+	 * 1 = page
+	 * 2 = (logical) bank
+	 * 3 = superbank (only if CS interleaving is enabled)
+	 */
+	popts->memctl_interleaving_mode = 0;
+
+	/*
+	 * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
+	 * 1: page:      bit to the left of the column bits selects the memctl
+	 * 2: bank:      bit to the left of the bank bits selects the memctl
+	 * 3: superbank: bit to the left of the chip select selects the memctl
+	 *
+	 * NOTE: ba_intlv (rank interleaving) is independent of memory
+	 * controller interleaving; it is only within a memory controller.
+	 * Must use superbank interleaving if rank interleaving is used and
+	 * memory controller interleaving is enabled.
+	 */
+
+	/*
+	 * 0 = no
+	 * 0x40 = CS0,CS1
+	 * 0x20 = CS2,CS3
+	 * 0x60 = CS0,CS1 + CS2,CS3
+	 * 0x04 = CS0,CS1,CS2,CS3
+	 */
+	popts->ba_intlv_ctl = 0;
+
+	/* Memory Organization Parameters */
+	popts->registered_dimm_en = pcommon_params->all_DIMMs_registered;
+
+
+	/* Operational Mode Paramters */
+
+	/*
+	 * Pick SDRAM type
+	 *
+	 * 2 = DDR1
+	 * 3 = DDR2
+	 * 6 = LPDDR1
+	 * 7 = DDR3
+	 */
+	popts->sdram_type = fsl_ddr_type_function();
+
+	/* Pick ECC modes */
+#ifdef CONFIG_DDR_ECC
+	popts->ECC_mode = 1;		  /* 0 = disabled, 1 = enabled */
+#else
+	popts->ECC_mode = 0;		  /* 0 = disabled, 1 = enabled */
+#endif
+	popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
+
+	/*
+	 * Choose DQS config
+	 * 0 for DDR1
+	 * 1 for DDR2
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	popts->DQS_config = 0;
+#elif defined(CONFIG_FSL_DDR2)
+	popts->DQS_config = 1;
+#else
+#error "Fix DQS for DDR3"
+#endif
+
+	/* Choose self-refresh during sleep. */
+	popts->self_refresh_in_sleep = 1;
+
+	/* Choose dynamic power management mode. */
+	popts->dynamic_power = 0;
+
+	/*
+	 * Choose dynamic power management mode.
+	 *
+	 * 0 = 64-bit
+	 * 1 = 32-bit
+	 * 2 = 16-bit
+	 */
+	popts->data_bus_width = 0;
+
+	/* Choose burst length. */
+	popts->burst_length = 4;	/* has to be 4 for DDR2 */
+
+	/* Global Timing Parameters. */
+	debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
+
+	/* Pick a caslat override. */
+	popts->cas_latency_override = 0;
+	popts->cas_latency_override_value = 3;
+	if (popts->cas_latency_override) {
+		debug("using caslat override value = %u\n",
+		       popts->cas_latency_override_value);
+	}
+
+	/*
+	 * Decide whether to use the computed derated latency
+	 * Should this be board specific?
+	 */
+	popts->use_derated_caslat = 0;
+
+	/* Choose an additive latency. */
+	popts->additive_latency_override = 0;
+	popts->additive_latency_override_value = 3;
+	if (popts->additive_latency_override) {
+		debug("using additive latency override value = %u\n",
+		       popts->additive_latency_override_value);
+	}
+
+	/*
+	 * Compute write latency.
+	 *
+	 * Total write latency = WR_LAT + ADD_LAT
+	 * WL = Read latency - 1 = CL + AL - 1
+	 */
+
+	/*
+	 * Select clock adjust
+	 *
+	 * Factors to consider for clock adjust:
+	 *	- number of chips on bus
+	 *	- position of slot
+	 *	- DDR1 vs. DDR2?
+	 *	- ???
+	 *
+	 * This needs to be determined on a board-by-board basis.
+	 *	0110	3/4 cycle late
+	 *	0111	7/8 cycle late
+	 */
+	popts->clk_adjust = fsl_ddr_clk_adjust_function();
+
+	/*
+	 * Select CPO override
+	 *
+	 * Factors to consider for CPO:
+	 *	- frequency
+	 *	- ddr1 vs. ddr2
+	 */
+	popts->cpo_override = fsl_ddr_cpo_override_function();
+
+	/*
+	 * Select write data delay
+	 *
+	 * Factors to consider for write data delay:
+	 *	- number of DIMMs
+	 *
+	 * 1 = 1/4 clock delay
+	 * 2 = 1/2 clock delay
+	 * 3 = 3/4 clock delay
+	 * 4 = 1   clock delay
+	 * 5 = 5/4 clock delay
+	 * 6 = 3/2 clock delay
+	 */
+	popts->write_data_delay = fsl_ddr_write_data_delay_function();
+
+	/*
+	 * FIXME -- Move to a board-specific file
+	 *
+	 * Half-strength driver enable
+	 *
+	 * Factors to consider for half-strength driver enable:
+	 *	- number of DIMMs installed
+	 */
+	popts->half_strength_driver_enable
+		= fsl_ddr_half_strength_driver_enable_function();
+
+	/*
+	 * 2T_EN setting
+	 *
+	 * Factors to consider for 2T_EN:
+	 *	- number of DIMMs installed
+	 *	- number of components, number of active ranks
+	 *	- how much time you want to spend playing around
+	 */
+	popts->twoT_en = 1;
+	popts->threeT_en = 0;
+
+	/*
+	 * BSTTOPRE precharge interval
+	 *
+	 * Set this to 0 for global auto precharge
+	 *
+	 * FIXME: Should this be configured in picoseconds?
+	 * Why it should be in ps:  better understanding of this
+	 * relative to actual DRAM timing parameters such as tRAS.
+	 * e.g. tRAS(min) = 40 ns
+	 */
+	popts->bstopre = 0x100;
+
+	/* Minimum CKE pulse width -- tCKE(MIN) */
+	popts->tCKE_clock_pulse_width_ps
+		= mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
+
+	/*
+	 * Window for four activates -- tFAW
+	 *
+	 * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
+	 * FIXME: varies depending upon number of column addresses or data
+	 * FIXME: width, was considering looking at pdimm->primary_sdram_width
+	 */
+#if defined(CONFIG_FSL_DDR1)
+	popts->tFAW_window_four_activates_ps = mclk_to_picos(1);
+
+#elif defined(CONFIG_FSL_DDR2)
+	/*
+	 * x4/x8;  some datasheets have 35000
+	 * x16 wide columns only?  Use 50000?
+	 */
+	popts->tFAW_window_four_activates_ps = 37500;
+
+#elif defined(CONFIG_FSL_DDR3)
+#error "FIXME determine four activates for DDR3"
+#endif
+
+	/* ODT should only be used for DDR2 */
+
+	/* FIXME? */
+
+	/*
+	 * Interleaving checks.
+	 *
+	 * If memory controller interleaving is enabled, then the data
+	 * bus widths must be programmed identically for the 2 memory
+	 * controllers.
+	 */
+
+	return 0;
+}
+
+int step_assign_addresses(fsl_ddr_info_t *pinfo,
+			  unsigned int dbw_cap_adj[],
+			  unsigned int *memctl_interleaving,
+			  unsigned int *rank_interleaving)
+{
+	int i, j;
+
+	/*
+	 * If a reduced data width is requested, but the SPD
+	 * specifies a physically wider device, adjust the
+	 * computed dimm capacities accordingly before
+	 * assigning addresses.
+	 */
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		unsigned int found = 0;
+
+		switch (pinfo->memctl_opts[i].data_bus_width) {
+		case 2:
+			/* 16-bit */
+			printf("can't handle 16-bit mode yet\n");
+			break;
+
+		case 1:
+			/* 32-bit */
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				unsigned int dw;
+				dw = pinfo->dimm_params[i][j].data_width;
+				if (pinfo->dimm_params[i][j].n_ranks
+				    && (dw == 72 || dw == 64)) {
+					/*
+					 * FIXME: can't really do it
+					 * like this because this just
+					 * further reduces the memory
+					 */
+					found = 1;
+					break;
+				}
+			}
+			if (found) {
+				dbw_cap_adj[i] = 1;
+				/* FIXME: 2 for 16-bit bus? */
+			}
+			break;
+
+		case 0:
+			/* 64-bit */
+			break;
+
+		default:
+			printf("unexpected data bus width "
+				"specified controller %u\n", i);
+			return 1;
+		}
+	}
+
+	/*
+	 * Check if all controllers are configured for memory
+	 * controller interleaving.
+	 */
+	j = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		if (pinfo->memctl_opts[i].memctl_interleaving) {
+			j++;
+		}
+	}
+	if (j == 2) {
+		*memctl_interleaving = 1;
+	}
+
+	/* Check that all controllers are rank interleaving. */
+	j = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		if (pinfo->memctl_opts[i].ba_intlv_ctl) {
+			j++;
+		}
+	}
+	if (j == 2) {
+		*rank_interleaving = 1;
+	}
+
+	if (*memctl_interleaving) {
+		phys_addr_t addr;
+
+		/*
+		 * If interleaving between memory controllers,
+		 * make each controller start at a base address
+		 * of 0.
+		 *
+		 * Also, if bank interleaving (chip select
+		 * interleaving) is enabled on each memory
+		 * controller, CS0 needs to be programmed to
+		 * cover the entire memory range on that memory
+		 * controller
+		 *
+		 * Bank interleaving also implies that each
+		 * addressed chip select is identical in size.
+		 */
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			addr = 0;
+			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]);
+			}
+		}
+	} else {
+		/*
+		 * Simple linear assignment if memory
+		 * controllers are not interleaved.
+		 */
+		phys_size_t cur_memsize = 0;
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			phys_size_t total_mem_per_ctlr = 0;
+			pinfo->common_timing_params[i].base_address =
+						(phys_addr_t)cur_memsize;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				/* Compute DIMM base addresses. */
+				unsigned long long cap =
+					pinfo->dimm_params[i][j].capacity;
+
+				pinfo->dimm_params[i][j].base_address =
+					(phys_addr_t)cur_memsize;
+				cur_memsize += cap >> dbw_cap_adj[i];
+				total_mem_per_ctlr += cap >> dbw_cap_adj[i];
+			}
+			pinfo->common_timing_params[i].total_mem =
+							total_mem_per_ctlr;
+		}
+	}
+
+	return 0;
+}
+
+phys_size_t
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step)
+{
+	unsigned int i, j;
+	unsigned int all_controllers_memctl_interleaving = 0;
+	unsigned int all_controllers_rank_interleaving = 0;
+	phys_size_t total_mem = 0;
+
+	fsl_memctl_config_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
+	common_timing_params_t *timing_params = pinfo->common_timing_params;
+
+	/* data bus width capacity adjust shift amount */
+	unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS];
+
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		dbw_capacity_adjust[i] = 0;
+	}
+
+	debug("starting@step %u (%s)\n",
+	      start_step, step_to_string(__ilog2(start_step)));
+
+	switch (start_step) {
+	case STEP_GET_SPD:
+		/* STEP 1:  Gather all DIMM SPD data */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i);
+		}
+
+	case STEP_COMPUTE_DIMM_PARMS:
+		/* STEP 2:  Compute DIMM parameters from SPD data */
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				unsigned int retval;
+				generic_spd_eeprom_t *spd =
+					&(pinfo->spd_installed_dimms[i][j]);
+				dimm_params_t *pdimm =
+                                        &(pinfo->dimm_params[i][j]);
+
+				retval = compute_dimm_parameters(spd, pdimm, i);
+				if (retval == 2) {
+					printf("Error: compute_dimm_parameters"
+					" non-zero returned FATAL value "
+					"for memctl=%u dimm=%u\n", i, j);
+					return 0;
+				}
+				if (retval) {
+					debug("Warning: compute_dimm_parameters"
+					" non-zero return value for memctl=%u "
+					"dimm=%u\n", i, j);
+				}
+			}
+		}
+
+	case STEP_COMPUTE_COMMON_PARMS:
+		/*
+		 * STEP 3: Compute a common set of timing parameters
+		 * suitable for all of the DIMMs on each memory controller
+		 */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			debug("Computing lowest common DIMM"
+				" parameters for memctl=%u\n", i);
+			compute_lowest_common_dimm_parameters(
+				pinfo->dimm_params[i],
+				&timing_params[i],
+				CONFIG_DIMM_SLOTS_PER_CTLR);
+		}
+
+	case STEP_GATHER_OPTS:
+		/* STEP 4:  Gather configuration requirements from user */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			debug("Reloading memory controller "
+				"configuration options for memctl=%u\n", i);
+			/*
+			 * This "reloads" the memory controller options
+			 * to defaults.  If the user "edits" an option,
+			 * next_step points to the step after this,
+			 * which is currently STEP_ASSIGN_ADDRESSES.
+			 */
+			populate_memctl_options(
+				&timing_params[i], &pinfo->memctl_opts[i], i);
+		}
+
+	case STEP_ASSIGN_ADDRESSES:
+		/* STEP 5:  Assign addresses to chip selects */
+		step_assign_addresses(pinfo,
+				dbw_capacity_adjust,
+				&all_controllers_memctl_interleaving,
+				&all_controllers_rank_interleaving);
+
+	case STEP_COMPUTE_REGS:
+		/* STEP 6:  compute controller register values */
+		debug("FSL Memory ctrl cg register computation\n");
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (timing_params[i].ndimms_present == 0) {
+				memset(&ddr_reg[i], 0,
+					sizeof(fsl_memctl_config_regs_t));
+				continue;
+			}
+
+			compute_fsl_memctl_config_regs(
+					&pinfo->memctl_opts[i],
+					&ddr_reg[i], &timing_params[i],
+					pinfo->dimm_params[i],
+					dbw_capacity_adjust[i]);
+		}
+
+	default:
+		break;
+	}
+
+	/* Compute the total amount of memory. */
+
+	/*
+	 * If bank interleaving but NOT memory controller interleaving
+	 * CS_BNDS describe the quantity of memory on each memory
+	 * controller, so the total is the sum across.
+	 */
+	if (!all_controllers_memctl_interleaving
+	    && all_controllers_rank_interleaving) {
+		total_mem = 0;
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			total_mem += timing_params[i].total_mem;
+		}
+
+	} else {
+		/*
+		 * Compute the amount of memory available just by
+		 * looking for the highest valid CSn_BNDS value.
+		 * This allows us to also experiment with using
+		 * only CS0 when using dual-rank DIMMs.
+		 */
+		unsigned int max_end = 0;
+
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) {
+				fsl_memctl_config_regs_t *reg = &ddr_reg[i];
+				if (reg->cs[j].config & 0x80000000) {
+					unsigned int end;
+					end = reg->cs[j].bnds & 0xFFF;
+					if (end > max_end) {
+						max_end = end;
+					}
+				}
+			}
+		}
+
+#if !defined(CONFIG_PHYS_64BIT)
+		/* Check for 4G or more with a 32-bit phys_addr_t.  Bad. */
+		if (max_end >= 0xff) {
+			printf("This U-Boot only supports < 4G of DDR\n");
+			printf("You could rebuild it with CONFIG_PHYS_64BIT\n");
+			return 0;	/* Ensure DDR setup failure. */
+		}
+#endif
+
+		total_mem = 1 + (((unsigned long long)max_end << 24ULL)
+				    | 0xFFFFFFULL);
+	}
+
+	return total_mem;
+}
+
+/*
+ * fsl_ddr_sdram() -- this is the main function to be called by
+ *	initdram() in the board file.
+ *
+ * It returns amount of memory configured in bytes.
+ */
+phys_size_t fsl_ddr_sdram(void)
+{
+	unsigned int i;
+	unsigned int memctl_interleaved;
+	phys_size_t total_memory;
+	fsl_ddr_info_t info;
+
+	/* Reset info structure. */
+	memset(&info, 0, sizeof(fsl_ddr_info_t));
+
+	/* Compute it once normally. */
+	total_memory = fsl_ddr_compute(&info, STEP_GET_SPD);
+
+	/* Check for memory controller interleaving. */
+	memctl_interleaved = 0;
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		memctl_interleaved +=
+			info.memctl_opts[i].memctl_interleaving;
+	}
+
+	if (memctl_interleaved) {
+		if (memctl_interleaved == CONFIG_NUM_DDR_CONTROLLERS) {
+			debug("memctl interleaving\n");
+			/*
+			 * Change the meaning of memctl_interleaved
+			 * to be "boolean".
+			 */
+			memctl_interleaved = 1;
+		} else {
+			printf("Error: memctl interleaving not "
+				"properly configured on all controllers\n");
+			while (1);
+		}
+	}
+
+	/* Program configuration registers. */
+	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+		debug("Programming controller %u\n", i);
+		if (info.common_timing_params[i].ndimms_present == 0) {
+			debug("No dimms present on controller %u; "
+					"skipping programming\n", i);
+			continue;
+		}
+
+		fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]),
+					      i);
+
+#ifdef DEBUG
+		fsl_ddr_dump_memctl_regs(i);
+#endif
+	}
+
+	if (memctl_interleaved) {
+		const unsigned int ctrl_num = 0;
+
+		/* Only set LAWBAR1 if memory controller interleaving is on. */
+		fsl_ddr_set_lawbar(&info.common_timing_params[0],
+					 memctl_interleaved, ctrl_num);
+	} else {
+		/*
+		 * Memory controller interleaving is NOT on;
+		 * set each lawbar individually.
+		 */
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			fsl_ddr_set_lawbar(&info.common_timing_params[i],
+						 0, i);
+		}
+	}
+
+	debug("total_memory = %llu\n", (u64)total_memory);
+
+	return total_memory;
+}
diff --git a/cpu/mpc8xxx/fsl_ddr_sdram.h b/cpu/mpc8xxx/fsl_ddr_sdram.h
new file mode 100644
index 0000000..58cac09
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr_sdram.h
@@ -0,0 +1,90 @@
+/*
+ * 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 FSL_DDR_MEMCTL_H
+#define FSL_DDR_MEMCTL_H
+
+/*
+ * Pick a basic DDR Technology.
+ */
+#include <ddr_spd.h>
+
+#if defined(CONFIG_FSL_DDR1)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(1)
+typedef ddr1_spd_eeprom_t generic_spd_eeprom_t;
+#elif defined(CONFIG_FSL_DDR2)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(3)
+typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
+#elif defined(CONFIG_FSL_DDR3)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(3)	/* FIXME */
+typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
+#endif
+
+/* FIXME: Trying to make this be generic... */
+#include "ddr2_dimm_params.h"
+
+#include "memctl_options.h"
+#include "common_timing_params.h"
+#include "fsl_memctrl.h"
+
+phys_size_t fsl_ddr_sdram(void);
+
+unsigned int mclk_to_picos(unsigned int mclk);
+unsigned int get_memory_clk_period_ps(void);
+unsigned int picos_to_mclk(unsigned int picos);
+
+/*
+ * Data Structures
+ *
+ * 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
+
+typedef struct {
+	generic_spd_eeprom_t
+	   spd_installed_dimms[CFG_NUM_DDR_CTLRS][CFG_DIMM_SLOTS_PER_CTLR];
+	dimm_params_t
+	   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_memctl_config_regs_t fsl_ddr_config_reg[CFG_NUM_DDR_CTLRS];
+} fsl_ddr_info_t;
+
+
+extern phys_size_t
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step);
+
+extern const char * step_to_string(unsigned int step);
+/*
+ * Compute steps
+ */
+#define STEP_GET_SPD                 (1 << 0)
+#define STEP_COMPUTE_DIMM_PARMS      (1 << 1)
+#define STEP_COMPUTE_COMMON_PARMS    (1 << 2)
+#define STEP_GATHER_OPTS             (1 << 3)
+#define STEP_ASSIGN_ADDRESSES        (1 << 4)
+#define STEP_COMPUTE_REGS            (1 << 5)
+#define STEP_PROGRAM_REGS            (1 << 6)
+#define STEP_ALL                     0xFFF
+
+/*
+ * Bind the main DDR setup driver's generic names
+ * to this specific DDR technology.
+ */
+
+static __inline__ int
+compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+			dimm_params_t *pdimm,
+			unsigned int dimm_number)
+{
+	return ddr_compute_dimm_parameters(spd, pdimm, dimm_number);
+}
+
+#endif
diff --git a/cpu/mpc8xxx/fsl_memctrl.h b/cpu/mpc8xxx/fsl_memctrl.h
new file mode 100644
index 0000000..b3f45a7
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_memctrl.h
@@ -0,0 +1,44 @@
+/*
+ * 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 FSL_MEMCTRL_H
+#define FSL_MEMCTRL_H
+
+/* Record of register values computed */
+typedef struct fsl_memctl_config_regs_s {
+	struct {
+		unsigned int bnds;
+		unsigned int config;
+		unsigned int config_2;
+	} cs[CONFIG_CHIP_SELECTS_PER_CTRL];
+	unsigned int timing_cfg_3;
+	unsigned int timing_cfg_0;
+	unsigned int timing_cfg_1;
+	unsigned int timing_cfg_2;
+	unsigned int ddr_sdram_cfg;
+	unsigned int ddr_sdram_cfg_2;
+	unsigned int ddr_sdram_mode;
+	unsigned int ddr_sdram_mode_2;
+	unsigned int ddr_sdram_interval;
+	unsigned int ddr_data_init;
+	unsigned int ddr_sdram_clk_cntl;
+	unsigned int ddr_init_addr;
+	unsigned int ddr_init_ext_addr;
+	unsigned int timing_cfg_4;
+	unsigned int timing_cfg_5;
+	unsigned int ddr_zq_cntl;
+	unsigned int ddr_wrlvl_cntl;
+	unsigned int ddr_pd_cntl;
+	unsigned int ddr_sr_cntr;
+	unsigned int ddr_sdram_rcw_1;
+	unsigned int ddr_sdram_rcw_2;
+} fsl_memctl_config_regs_t;
+
+unsigned int check_fsl_memctl_config_regs(const fsl_memctl_config_regs_t *ddr);
+
+#endif /* FSL_MEMCTRL_H */
diff --git a/cpu/mpc8xxx/fsl_util.c b/cpu/mpc8xxx/fsl_util.c
new file mode 100644
index 0000000..aa1562d
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_util.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+
+unsigned int fsl_ddr_get_mem_data_rate(void);
+
+/*
+ * Round mclk_ps to nearest 10 ps in memory controller code.
+ *
+ * If an imprecise data rate is too high due to rounding error
+ * propagation, compute a suitably rounded mclk_ps to compute
+ * a working memory controller configuration.
+ */
+unsigned int get_memory_clk_period_ps(void)
+{
+	unsigned int mclk_ps;
+
+	mclk_ps = 2000000000000ULL / fsl_ddr_get_mem_data_rate();
+	/* round to nearest 10 ps */
+	return 10 * ((mclk_ps + 5) / 10);
+}
+
+/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */
+unsigned int picos_to_mclk(unsigned int picos)
+{
+	const unsigned long long ULL_2e12 = 2000000000000ULL;
+	const unsigned long long ULL_8Fs = 0xFFFFFFFFULL;
+	unsigned long long clks;
+	unsigned long long clks_temp;
+
+	if (!picos)
+		return 0;
+
+	clks = fsl_ddr_get_mem_data_rate() * (unsigned long long) picos;
+	clks_temp = clks;
+	clks = clks / ULL_2e12;
+	if (clks_temp % ULL_2e12) {
+		clks++;
+	}
+
+	if (clks > ULL_8Fs) {
+		clks = ULL_8Fs;
+	}
+
+	return (unsigned int) clks;
+}
+
+unsigned int mclk_to_picos(unsigned int mclk)
+{
+	return get_memory_clk_period_ps() * mclk;
+}
+
+
diff --git a/cpu/mpc8xxx/memctl_options.h b/cpu/mpc8xxx/memctl_options.h
new file mode 100644
index 0000000..0cdce1d
--- /dev/null
+++ b/cpu/mpc8xxx/memctl_options.h
@@ -0,0 +1,85 @@
+/*
+ * 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 MEMCTL_OPTIONS_H
+#define MEMCTL_OPTIONS_H
+
+#include "common_timing_params.h"
+
+typedef struct memctl_options_partial_s {
+	unsigned int all_DIMMs_ECC_capable;
+	unsigned int all_DIMMs_tCKmax_ps;
+	unsigned int all_DIMMs_burst_lengths_bitmask;
+	unsigned int all_DIMMs_registered;
+	unsigned int all_DIMMs_unbuffered;
+	/*	unsigned int lowest_common_SPD_caslat; */
+	unsigned int all_DIMMs_minimum_tRCD_ps;
+} memctl_options_partial_t;
+
+/*
+ * Generalized parameters for memory controller configuration,
+ * might be a little specific to the FSL memory controller
+ */
+typedef struct memctl_options_s {
+	/*
+	 * Memory organization parameters
+	 *
+	 * if DIMM is present in the system
+	 * where DIMMs are with respect to chip select
+	 * where chip selects are with respect to memory boundaries
+	 */
+	unsigned int registered_dimm_en;    /* use registered DIMM support */
+
+	/* Options local to a Chip Select */
+	struct cs_local_opts_s {
+		unsigned int auto_precharge;
+		unsigned int odt_rd_cfg;
+		unsigned int odt_wr_cfg;
+	} cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL];
+
+	/* Special configurations for chip select */
+	unsigned int memctl_interleaving;
+	unsigned int memctl_interleaving_mode;
+	unsigned int ba_intlv_ctl;
+
+	/* Operational mode parameters */
+	unsigned int sdram_type; /* 2 = DDR1, 3 = DDR2, 6 = LPDDR1, 7 = DDR3 */
+	unsigned int ECC_mode;	 /* Use ECC? */
+	/* Initialize ECC using memory controller? */
+	unsigned int ECC_init_using_memctl;
+	unsigned int DQS_config;	/* Use DQS? maybe only with DDR2? */
+	/* SREN - self-refresh during sleep */
+	unsigned int self_refresh_in_sleep;
+	unsigned int dynamic_power;	/* DYN_PWR */
+	/* memory data width to use (16-bit, 32-bit, 64-bit) */
+	unsigned int data_bus_width;
+	unsigned int burst_length;	/* 4, 8 */
+
+	/* Global Timing Parameters */
+	unsigned int cas_latency_override;
+	unsigned int cas_latency_override_value;
+	unsigned int use_derated_caslat;
+	unsigned int additive_latency_override;
+	unsigned int additive_latency_override_value;
+
+	unsigned int clk_adjust;		/* */
+	unsigned int cpo_override;
+	unsigned int write_data_delay;		/* DQS adjust */
+	unsigned int half_strength_driver_enable;
+	unsigned int twoT_en;
+	unsigned int threeT_en;
+	unsigned int bstopre;
+	unsigned int tCKE_clock_pulse_width_ps;	/* tCKE */
+	unsigned int tFAW_window_four_activates_ps;	/* tFAW --  FOUR_ACT */
+} memctl_options_t;
+
+unsigned int populate_memctl_options(
+				const common_timing_params_t *ppartial_opts,
+				memctl_options_t *popts,
+				unsigned int ctrl_num);
+#endif
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support
  2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
@ 2008-08-20 23:22   ` Kumar Gala
  2008-08-20 23:22     ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Kumar Gala
  2008-08-26 23:08     ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Wolfgang Denk
  2008-08-26 23:08   ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Wolfgang Denk
  2008-08-29 22:16   ` Peter Tyser
  2 siblings, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Signed-off-by: James Yang <James.Yang@freescale.com>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 cpu/mpc8xxx/fsl_ddr1.c |  342 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 342 insertions(+), 0 deletions(-)
 create mode 100644 cpu/mpc8xxx/fsl_ddr1.c

diff --git a/cpu/mpc8xxx/fsl_ddr1.c b/cpu/mpc8xxx/fsl_ddr1.c
new file mode 100644
index 0000000..48308d0
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr1.c
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+
+#include "fsl_ddr_sdram.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ *		DDR I	DDR II
+ *	Bit	Size	Size
+ *	---	-----	------
+ *	7 high	512MB	512MB
+ *	6	256MB	256MB
+ *	5	128MB	128MB
+ *	4	 64MB	 16GB
+ *	3	 32MB	  8GB
+ *	2	 16MB	  4GB
+ *	1	  2GB	  2GB
+ *	0 low	  1GB	  1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ */
+
+static phys_size_t
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+	phys_size_t bsize;
+
+	/* Bottom 2 bits up to the top. */
+	bsize = ((row_dens >> 2) | ((row_dens & 3) << 6));
+	bsize <<= 24ULL;
+	debug("DDR: DDR I rank density = 0x%08x\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II.  No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+	/* Table look up the lower nibble, allow DDR I & II. */
+	unsigned int tenths_ps[16] = {
+		0,
+		100,
+		200,
+		300,
+		400,
+		500,
+		600,
+		700,
+		800,
+		900,
+		250,	/* This and the next 3 entries valid ... */
+		330,	/* ...  only for tCK calculations. */
+		660,
+		750,
+		0,	/* undefined */
+		0	/* undefined */
+	};
+
+	unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+	unsigned int tenth_ns = spd_val & 0x0F;
+	unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+	return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+	unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+	unsigned int hundredth_ns = spd_val & 0x0F;
+	unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+	return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+	0,
+	250,
+	330,
+	500,
+	660,
+	750,
+	0,	/* supposed to be RFC, but not sure what that means */
+	0	/* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+	unsigned int trfc_ps;
+
+	trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+		+ byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+	return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+	unsigned int trc_ps;
+
+	trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+	return trc_ps;
+}
+
+/*
+ * tCKmax from DDR I SPD Byte 43
+ *
+ * Bits 7:2 == whole ns
+ * Bits 1:0 == quarter ns
+ *    00    == 0.00 ns
+ *    01    == 0.25 ns
+ *    10    == 0.50 ns
+ *    11    == 0.75 ns
+ *
+ * Returns picoseconds.
+ */
+static unsigned int
+compute_tckmax_from_spd_ps(unsigned int byte43)
+{
+	return (byte43 >> 2) * 1000 + (byte43 & 0x3) * 250;
+}
+
+/*
+ * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+	unsigned int refresh_time_ps[8] = {
+		15625000,	/* 0 Normal    1.00x */
+		3900000,	/* 1 Reduced    .25x */
+		7800000,	/* 2 Extended   .50x */
+		31300000,	/* 3 Extended  2.00x */
+		62500000,	/* 4 Extended  4.00x */
+		125000000,	/* 5 Extended  8.00x */
+		15625000,	/* 6 Normal    1.00x  filler */
+		15625000,	/* 7 Normal    1.00x  filler */
+	};
+
+	return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period.  The SPD only
+ * defines at most 3 CAS latencies.  Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can be.
+ * If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD.  This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-E
+ * Table 11.
+ *
+ * ordinal 2, ddr1_speed_bins[1] contains tCK for CL=2
+ */
+				  /*   CL2.0 CL2.5 CL3.0  */
+unsigned short ddr1_speed_bins[] = {0, 7500, 6000, 5000 };
+
+unsigned int
+compute_derated_DDR1_CAS_latency(unsigned int mclk_ps)
+{
+	const unsigned int num_speed_bins = ARRAY_SIZE(ddr1_speed_bins);
+	unsigned int lowest_tCKmin_found = 0;
+	unsigned int lowest_tCKmin_CL = 0;
+	unsigned int i;
+
+	debug("mclk_ps = %u\n", mclk_ps);
+
+	for (i = 0; i < num_speed_bins; i++) {
+		unsigned int x = ddr1_speed_bins[i];
+		debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+		      i, x, lowest_tCKmin_found);
+		if (x && lowest_tCKmin_found <= x && x <= mclk_ps) {
+			lowest_tCKmin_found = x;
+			lowest_tCKmin_CL = i + 1;
+		}
+	}
+
+	debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+	return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR1 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR) {
+			printf("DIMM %u: is not a DDR1 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr1_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = spd->nrows;
+	pdimm->rank_density = compute_ranksize(spd->mem_type, spd->bank_dens);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->data_width = spd->dataw_lsb;
+	pdimm->primary_sdram_width = spd->primw;
+	pdimm->ec_sdram_width = spd->ecw;
+
+	/*
+	 * FIXME: Need to determine registered_dimm status.
+	 *     1 == register buffered
+	 *     0 == unbuffered
+	 */
+	pdimm->registered_dimm = 0;	/* unbuffered */
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = spd->nrow_addr;
+	pdimm->n_col_addr = spd->ncol_addr;
+	pdimm->n_banks_per_sdram_device = spd->nbanks;
+	pdimm->edc_config = spd->config;
+	pdimm->burst_lengths_bitmask = spd->burstl;
+	pdimm->row_density = spd->bank_dens;
+
+	/*
+	 * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+	 * The SPD clk_cycle field (tCKmin) is measured in tenths of
+	 * nanoseconds and represented as BCD.
+	 */
+	pdimm->tCKmin_X_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+	pdimm->tCKmin_X_minus_1_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+	pdimm->tCKmin_X_minus_2_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+	pdimm->tCKmax_ps = compute_tckmax_from_spd_ps(spd->tckmax);
+
+	/*
+	 * Compute CAS latencies defined by SPD
+	 * The SPD caslat_X should have at least 1 and at most 3 bits set.
+	 *
+	 * If cas_lat after masking is 0, the __ilog2 function returns
+	 * 255 into the variable.   This behavior is abused once.
+	 */
+	pdimm->caslat_X  = __ilog2(spd->cas_lat);
+	pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X));
+	pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X)
+					  & ~(1 << pdimm->caslat_X_minus_1));
+
+	/* Compute CAS latencies below that defined by SPD */
+	pdimm->caslat_lowest_derated
+		= compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps());
+
+	/* Compute timing parameters */
+	pdimm->tRCD_ps = spd->trcd * 250;
+	pdimm->tRP_ps = spd->trp * 250;
+	pdimm->tRAS_ps = spd->tras * 1000;
+
+	pdimm->tWR_ps = mclk_to_picos(3);
+	pdimm->tWTR_ps = mclk_to_picos(1);
+	pdimm->tRFC_ps = compute_trfc_ps_from_spd(0, spd->trfc);
+
+	pdimm->tRRD_ps = spd->trrd * 250;
+	pdimm->tRC_ps = compute_trc_ps_from_spd(0, spd->trc);
+
+	pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+	pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+	pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+	pdimm->tDS_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+	pdimm->tDH_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+	pdimm->tRTP_ps = mclk_to_picos(2);	/* By the book. */
+	pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+	pdimm->tQHS_ps = spd->tqhs * 10;
+
+	return 0;
+}
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support
  2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
@ 2008-08-20 23:22     ` Kumar Gala
  2008-08-20 23:22       ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Kumar Gala
  2008-08-26 23:08       ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Wolfgang Denk
  2008-08-26 23:08     ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Signed-off-by: James Yang <James.Yang@freescale.com>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 cpu/mpc8xxx/fsl_ddr2.c |  339 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 339 insertions(+), 0 deletions(-)
 create mode 100644 cpu/mpc8xxx/fsl_ddr2.c

diff --git a/cpu/mpc8xxx/fsl_ddr2.c b/cpu/mpc8xxx/fsl_ddr2.c
new file mode 100644
index 0000000..6b516e9
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr2.c
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+
+#include "fsl_ddr_sdram.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ *		DDR I	DDR II
+ *	Bit	Size	Size
+ *	---	-----	------
+ *	7 high	512MB	512MB
+ *	6	256MB	256MB
+ *	5	128MB	128MB
+ *	4	 64MB	 16GB
+ *	3	 32MB	  8GB
+ *	2	 16MB	  4GB
+ *	1	  2GB	  2GB
+ *	0 low	  1GB	  1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ *
+ */
+static phys_size_t
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+	phys_size_t bsize;
+
+	/* Bottom 5 bits up to the top. */
+	bsize = ((row_dens >> 5) | ((row_dens & 31) << 3));
+	bsize <<= 27ULL;
+	debug("DDR: DDR II rank density = 0x%08x\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II.  No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+	/* Table look up the lower nibble, allow DDR I & II. */
+	unsigned int tenths_ps[16] = {
+		0,
+		100,
+		200,
+		300,
+		400,
+		500,
+		600,
+		700,
+		800,
+		900,
+		250,	/* This and the next 3 entries valid ... */
+		330,	/* ...  only for tCK calculations. */
+		660,
+		750,
+		0,	/* undefined */
+		0	/* undefined */
+	};
+
+	unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+	unsigned int tenth_ns = spd_val & 0x0F;
+	unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+	return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+	unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+	unsigned int hundredth_ns = spd_val & 0x0F;
+	unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+	return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+	0,
+	250,
+	330,
+	500,
+	660,
+	750,
+	0,	/* supposed to be RFC, but not sure what that means */
+	0	/* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+	unsigned int trfc_ps;
+
+	trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+		+ byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+	return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+	unsigned int trc_ps;
+
+	trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+	return trc_ps;
+}
+
+/*
+ * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+	unsigned int refresh_time_ps[8] = {
+		15625000,	/* 0 Normal    1.00x */
+		3900000,	/* 1 Reduced    .25x */
+		7800000,	/* 2 Extended   .50x */
+		31300000,	/* 3 Extended  2.00x */
+		62500000,	/* 4 Extended  4.00x */
+		125000000,	/* 5 Extended  8.00x */
+		15625000,	/* 6 Normal    1.00x  filler */
+		15625000,	/* 7 Normal    1.00x  filler */
+	};
+
+	return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period.  The SPD only
+ * defines at most 3 CAS latencies.  Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can.
+ * be.  If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD.  This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-2C
+ * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS,
+ * and tRC for corresponding bin"
+ *
+ * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3
+ * Not certain if any good value exists for CL=2
+ */
+				 /* CL2   CL3   CL4   CL5   CL6 */
+unsigned short ddr2_speed_bins[] = {   0, 5000, 3750, 3000, 2500 };
+
+unsigned int
+compute_derated_DDR2_CAS_latency(unsigned int mclk_ps)
+{
+	const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins);
+	unsigned int lowest_tCKmin_found = 0;
+	unsigned int lowest_tCKmin_CL = 0;
+	unsigned int i;
+
+	debug("mclk_ps = %u\n", mclk_ps);
+
+	for (i = 0; i < num_speed_bins; i++) {
+		unsigned int x = ddr2_speed_bins[i];
+		debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+		      i, x, lowest_tCKmin_found);
+		if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) {
+			lowest_tCKmin_found = x;
+			lowest_tCKmin_CL = i + 2;
+		}
+	}
+
+	debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+	return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR2 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR2) {
+			printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr2_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1;
+	pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->data_width = spd->dataw;
+	pdimm->primary_sdram_width = spd->primw;
+	pdimm->ec_sdram_width = spd->ecw;
+
+	/* FIXME: what about registered SO-DIMM? */
+	switch (spd->dimm_type) {
+	case 0x01:	/* RDIMM */
+	case 0x10:	/* Mini-RDIMM */
+		pdimm->registered_dimm = 1; /* register buffered */
+		break;
+
+	case 0x02:	/* UDIMM */
+	case 0x04:	/* SO-DIMM */
+	case 0x08:	/* Micro-DIMM */
+	case 0x20:	/* Mini-UDIMM */
+		pdimm->registered_dimm = 0;	/* unbuffered */
+		break;
+
+	default:
+		printf("unknown dimm_type 0x%02X\n", spd->dimm_type);
+		return 1;
+		break;
+	}
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = spd->nrow_addr;
+	pdimm->n_col_addr = spd->ncol_addr;
+	pdimm->n_banks_per_sdram_device = spd->nbanks;
+	pdimm->edc_config = spd->config;
+	pdimm->burst_lengths_bitmask = spd->burstl;
+	pdimm->row_density = spd->rank_dens;
+
+	/*
+	 * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+	 * The SPD clk_cycle field (tCKmin) is measured in tenths of
+	 * nanoseconds and represented as BCD.
+	 */
+	pdimm->tCKmin_X_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+	pdimm->tCKmin_X_minus_1_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+	pdimm->tCKmin_X_minus_2_ps
+		= convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+	pdimm->tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax);
+
+	/*
+	 * Compute CAS latencies defined by SPD
+	 * The SPD caslat_X should have at least 1 and at most 3 bits set.
+	 *
+	 * If cas_lat after masking is 0, the __ilog2 function returns
+	 * 255 into the variable.   This behavior is abused once.
+	 */
+	pdimm->caslat_X  = __ilog2(spd->cas_lat);
+	pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X));
+	pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+					  & ~(1 << pdimm->caslat_X)
+					  & ~(1 << pdimm->caslat_X_minus_1));
+
+	/* Compute CAS latencies below that defined by SPD */
+	pdimm->caslat_lowest_derated
+		= compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps());
+
+	/* Compute timing parameters */
+	pdimm->tRCD_ps = spd->trcd * 250;
+	pdimm->tRP_ps = spd->trp * 250;
+	pdimm->tRAS_ps = spd->tras * 1000;
+
+	pdimm->tWR_ps = spd->twr * 250;
+	pdimm->tWTR_ps = spd->twtr * 250;
+	pdimm->tRFC_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc);
+
+	pdimm->tRRD_ps = spd->trrd * 250;
+	pdimm->tRC_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc);
+
+	pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+	pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+	pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+	pdimm->tDS_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+	pdimm->tDH_ps
+		= convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+	pdimm->tRTP_ps = spd->trtp * 250;
+	pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+	pdimm->tQHS_ps = spd->tqhs * 10;
+
+	return 0;
+}
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support
  2008-08-20 23:22     ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Kumar Gala
@ 2008-08-20 23:22       ` Kumar Gala
  2008-08-20 23:22         ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Kumar Gala
  2008-08-26 23:09         ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Wolfgang Denk
  2008-08-26 23:08       ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Provide a mechanism to allow interactive configuration of DDR params.  This
is useful when trying to test various DDR settings to determine optimal
configuration values for a given board.

Signed-off-by: James Yang <James.Yang@freescale.com>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 cpu/mpc8xxx/Makefile              |    2 +
 cpu/mpc8xxx/fsl_ddr_interactive.c | 1238 +++++++++++++++++++++++++++++++++++++
 cpu/mpc8xxx/fsl_ddr_sdram.c       |   12 +-
 cpu/mpc8xxx/fsl_ddr_sdram.h       |    3 +
 4 files changed, 1254 insertions(+), 1 deletions(-)
 create mode 100644 cpu/mpc8xxx/fsl_ddr_interactive.c

diff --git a/cpu/mpc8xxx/Makefile b/cpu/mpc8xxx/Makefile
index 888ebfe..660ab54 100644
--- a/cpu/mpc8xxx/Makefile
+++ b/cpu/mpc8xxx/Makefile
@@ -10,6 +10,8 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)libmpc8xxx.a
 
+COBJS-$(CONFIG_FSL_DDR_INTERACTIVE)	+= fsl_ddr_interactive.o
+
 COBJS-$(CONFIG_FSL_DDR1)	+= fsl_ddr_sdram.o fsl_util.o fsl_ddr_ctrl.o
 COBJS-$(CONFIG_FSL_DDR1)	+= fsl_ddr1.o
 
diff --git a/cpu/mpc8xxx/fsl_ddr_interactive.c b/cpu/mpc8xxx/fsl_ddr_interactive.c
new file mode 100644
index 0000000..4e12756
--- /dev/null
+++ b/cpu/mpc8xxx/fsl_ddr_interactive.c
@@ -0,0 +1,1238 @@
+/*
+ * 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.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <linux/ctype.h>
+#include <asm/types.h>
+
+#include "fsl_ddr_sdram.h"
+/* Option parameter Structures */
+typedef struct {
+	const char *option_name;
+	unsigned long long *pointer;
+} options_strings_ulonglong_t;
+
+typedef struct {
+	const char *option_name;
+	unsigned int *pointer;
+} options_strings_uint_t;
+
+
+extern int do_reset(void *cmdtp, int flag, int argc, char *argv[]);
+
+static unsigned int picos_to_mhz(unsigned int picos)
+{
+	return 1000000 / picos;
+}
+
+static int
+handle_uint_option_table(options_strings_uint_t *table,
+			 int table_size,
+			 const char *opt,
+			 const char *val)
+{
+	unsigned int i;
+	unsigned int value;
+
+	for (i = 0; i < table_size; i++) {
+		if (strcmp(table[i].option_name, opt) == 0) {
+			value = simple_strtoul(val, NULL, 0);
+			*table[i].pointer = value;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+handle_ull_option_table(options_strings_ulonglong_t *table,
+			int table_size,
+			const char *opt,
+			const char *val)
+{
+	unsigned int i;
+	unsigned long long value;
+
+	for (i = 0; i < table_size; i++) {
+		if (strcmp(table[i].option_name, opt) == 0) {
+			value = simple_strtoull(val, NULL, 0);
+			*table[i].pointer = value;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static void
+fsl_ddr_generic_edit(void *pdata,
+			   void *pend,
+			   unsigned int element_size,
+			   unsigned int element_num,
+			   unsigned int value)
+{
+	char *pcdata = (char *)pdata;		/* BIG ENDIAN ONLY */
+
+	pcdata += element_num * element_size;
+	if ((pcdata + element_size) > (char *) pend) {
+		debug("trying to write past end of data\n");
+		return;
+	}
+
+	switch (element_size) {
+	case 1:
+		asm volatile ("stb %0,0(%1)" : : "r" (value) , "b" (pcdata));
+		break;
+	case 2:
+		asm volatile ("sth %0,0(%1)" : : "r" (value) , "b" (pcdata));
+		break;
+	case 4:
+		asm volatile ("stw %0,0(%1)" : : "r" (value) , "b" (pcdata));
+		break;
+	default:
+		debug("unexpected element size %u\n", element_size);
+		break;
+	}
+}
+
+static void
+fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
+		       unsigned int ctrl_num,
+		       unsigned int dimm_num,
+		       unsigned int element_num,
+		       unsigned int value)
+{
+	generic_spd_eeprom_t *pspd;
+
+	pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
+	fsl_ddr_generic_edit(pspd, pspd + 1,
+				   sizeof(char), element_num, value);
+}
+
+static void
+lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+					unsigned int ctrl_num,
+					const char *optname_str,
+					const char * value_str)
+{
+	common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];
+
+	options_strings_uint_t options_uint[] = {
+		{"tCKmin_X_ps",                     &p->tCKmin_X_ps},
+		{"tCKmax_ps",                       &p->tCKmax_ps},
+		{"tCKmax_max_ps",                   &p->tCKmax_max_ps},
+		{"tRCD_ps",                         &p->tRCD_ps},
+		{"tRP_ps",                          &p->tRP_ps},
+		{"tRAS_ps",                         &p->tRAS_ps},
+		{"tWR_ps",                          &p->tWR_ps},
+		{"tWTR_ps",                         &p->tWTR_ps},
+		{"tRFC_ps",                         &p->tRFC_ps},
+		{"tRRD_ps",                         &p->tRRD_ps},
+		{"tRC_ps",                          &p->tRC_ps},
+		{"refresh_rate_ps",                 &p->refresh_rate_ps},
+		{"tIS_ps",                          &p->tIS_ps},
+		{"tIH_ps",                          &p->tIH_ps},
+		{"tDS_ps",                          &p->tDS_ps},
+		{"tDH_ps",                          &p->tDH_ps},
+		{"tRTP_ps",                         &p->tRTP_ps},
+		{"tDQSQ_max_ps",                    &p->tDQSQ_max_ps},
+		{"tQHS_ps",                         &p->tQHS_ps},
+		{"ndimms_present",                  &p->ndimms_present},
+		{"lowest_common_SPD_caslat",
+			&p->lowest_common_SPD_caslat},
+		{"highest_common_derated_caslat",
+			&p->highest_common_derated_caslat},
+		{"additive_latency",                &p->additive_latency},
+		{"all_DIMMs_burst_lengths_bitmask",
+			&p->all_DIMMs_burst_lengths_bitmask},
+		{"all_DIMMs_registered",            &p->all_DIMMs_registered},
+		{"all_DIMMs_unbuffered",            &p->all_DIMMs_unbuffered},
+		{"all_DIMMs_ECC_capable",           &p->all_DIMMs_ECC_capable}
+	};
+
+	const unsigned int n_uint_opts = ARRAY_SIZE(options_uint);
+
+	options_strings_ulonglong_t options_ull[] = {
+		{"total_mem",    &p->total_mem},
+		{"base_address", &p->base_address}
+	};
+
+	const unsigned int n_ull_opts = ARRAY_SIZE(options_ull);
+
+	if (handle_uint_option_table(options_uint, n_uint_opts,
+				     optname_str, value_str))
+		return;
+
+	if (handle_ull_option_table(options_ull, n_ull_opts,
+				    optname_str, value_str))
+		return;
+
+	printf("Error: couldn't find option string %s\n", optname_str);
+}
+
+static void
+fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+				   unsigned int ctrl_num,
+				   unsigned int dimm_num,
+				   const char *optname_str,
+				   const char *value_str)
+{
+	dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]);
+
+	options_strings_uint_t options_uint[] = {
+		{"n_ranks",                  &p->n_ranks},
+		{"data_width",               &p->data_width},
+		{"primary_sdram_width",      &p->primary_sdram_width},
+		{"ec_sdram_width",           &p->ec_sdram_width},
+		{"registered_dimm",          &p->registered_dimm},
+
+		{"n_row_addr",               &p->n_row_addr},
+		{"n_col_addr",               &p->n_col_addr},
+		{"edc_config",               &p->edc_config},
+		{"n_banks_per_sdram_device", &p->n_banks_per_sdram_device},
+		{"burst_lengths_bitmask",    &p->burst_lengths_bitmask},
+		{"row_density",              &p->row_density},
+
+		{"tCKmin_X_ps",              &p->tCKmin_X_ps},
+		{"tCKmin_X_minus_1_ps",      &p->tCKmin_X_minus_1_ps},
+		{"tCKmin_X_minus_2_ps",      &p->tCKmin_X_minus_2_ps},
+		{"tCKmax_ps",                &p->tCKmax_ps},
+
+		{"caslat_X",                 &p->caslat_X},
+		{"caslat_X_minus_1",         &p->caslat_X_minus_1},
+		{"caslat_X_minus_2",         &p->caslat_X_minus_2},
+
+		{"caslat_lowest_derated",    &p->caslat_lowest_derated},
+
+		{"tRCD_ps",                  &p->tRCD_ps},
+		{"tRP_ps",                   &p->tRP_ps},
+		{"tRAS_ps",                  &p->tRAS_ps},
+		{"tWR_ps",                   &p->tWR_ps},
+		{"tWTR_ps",                  &p->tWTR_ps},
+		{"tRFC_ps",                  &p->tRFC_ps},
+		{"tRRD_ps",                  &p->tRRD_ps},
+		{"tRC_ps",                   &p->tRC_ps},
+		{"refresh_rate_ps",          &p->refresh_rate_ps},
+
+		{"tIS_ps",                   &p->tIS_ps},
+		{"tIH_ps",                   &p->tIH_ps},
+		{"tDS_ps",                   &p->tDS_ps},
+		{"tDH_ps",                   &p->tDH_ps},
+		{"tRTP_ps",                  &p->tRTP_ps},
+		{"tDQSQ_max_ps",             &p->tDQSQ_max_ps},
+		{"tQHS_ps",                  &p->tQHS_ps},
+	};
+
+	const unsigned int n_uint_opts = ARRAY_SIZE(options_uint);
+
+	options_strings_ulonglong_t options_ull[] = {
+		{"rank_density",  &p->rank_density},
+		{"capacity", &p->capacity},
+		{"base_address",  &p->base_address},
+	};
+
+	const unsigned int n_ull_opts = ARRAY_SIZE(options_ull);
+
+	if (handle_uint_option_table(options_uint, n_uint_opts,
+				     optname_str, value_str))
+		return;
+
+	if (handle_ull_option_table(options_ull, n_ull_opts,
+				    optname_str, value_str))
+		return;
+
+	printf("couldn't find option string %s\n", optname_str);
+}
+
+static void
+print_dimm_parameters(const dimm_params_t *pdimm)
+{
+	if (pdimm->n_ranks == 0) {
+		printf("DIMM not present\n");
+		return;
+	}
+
+	printf("DIMM organization parameters:\n");
+
+	printf("module part name = %s\n", pdimm->mpart);
+	printf("n_ranks = %u\n", pdimm->n_ranks);
+	printf("rank_density = %llu bytes (%llu megabytes)\n",
+	       pdimm->rank_density, pdimm->rank_density / 0x100000);
+	printf("capacity = %llu bytes (%llu megabytes)\n",
+	       pdimm->capacity, pdimm->capacity / 0x100000);
+	printf("data_width = %u\n", pdimm->data_width);
+	printf("primary_sdram_width = %u\n", pdimm->primary_sdram_width);
+	printf("ec_sdram_width = %u\n", pdimm->ec_sdram_width);
+	printf("registered_dimm = %u\n", pdimm->registered_dimm);
+
+	printf("SDRAM device parameters:\n");
+	printf("n_row_addr = %u\n", pdimm->n_row_addr);
+	printf("n_col_addr = %u\n", pdimm->n_col_addr);
+	printf("edc_config = %u\n", pdimm->edc_config);
+	printf("n_banks_per_sdram_device = %u\n",
+	       pdimm->n_banks_per_sdram_device);
+	printf("burst_lengths_bitmask = %02X\n",
+	       pdimm->burst_lengths_bitmask);
+
+	printf("base_addresss = %llu (%08llX %08llX)\n",
+	       pdimm->base_address,
+	       (pdimm->base_address >> 32),
+	       pdimm->base_address & 0xFFFFFFFF);
+
+	printf("SDRAM clock periods:\n");
+	printf("tCKmin_X_ps = %u ps\n", pdimm->tCKmin_X_ps);
+	printf("tCKmin_X_minus_1_ps = %u ps\n", pdimm->tCKmin_X_minus_1_ps);
+	printf("tCKmin_X_minus_2_ps = %u ps\n", pdimm->tCKmin_X_minus_2_ps);
+	printf("tCKmax_ps = %u ps\n", pdimm->tCKmax_ps);
+
+	printf("SDRAM CAS latencies:\n");
+	printf("caslat_X = %u\n", pdimm->caslat_X);
+	printf("caslat_X_minus_1 = %u\n", pdimm->caslat_X_minus_1);
+	printf("caslat_X_minus_2 = %u\n", pdimm->caslat_X_minus_2);
+	printf("caslat_lowest_derated = %u\n", pdimm->caslat_lowest_derated);
+
+	printf("SDRAM timing parameters:\n");
+	printf("tRCD_ps = %u\n", pdimm->tRCD_ps);
+	printf("tRP_ps = %u\n",  pdimm->tRP_ps);
+	printf("tRAS_ps = %u\n", pdimm->tRAS_ps);
+	printf("tWR_ps = %u\n",  pdimm->tWR_ps);
+	printf("tWTR_ps = %u\n", pdimm->tWTR_ps);
+	printf("tRFC_ps = %u\n", pdimm->tRFC_ps);
+	printf("tRC_ps = %u\n",  pdimm->tRC_ps);
+	printf("tRRD_ps = %u\n", pdimm->tRRD_ps);
+	printf("refresh_rate_ps = %u\n", pdimm->refresh_rate_ps);
+
+	printf("SDRAM even more timing parameters:\n");
+	printf("tIS_ps = %u\n", pdimm->tIS_ps);
+	printf("tIH_ps = %u\n", pdimm->tIH_ps);
+	printf("tDS_ps = %u\n", pdimm->tDS_ps);
+	printf("tDH_ps = %u\n", pdimm->tDH_ps);
+	printf("tRTP_ps = %u\n", pdimm->tRTP_ps);
+	printf("tDQSQ_max_ps = %u\n", pdimm->tDQSQ_max_ps);
+	printf("tQHS_ps = %u\n", pdimm->tQHS_ps);
+}
+
+static void
+print_lowest_common_dimm_parameters(
+		const common_timing_params_t *plcd_dimm_params)
+{
+
+	/* Clock frequencies */
+	printf("tCKmin_X_ps = %u (%u MHz)\n",
+	       plcd_dimm_params->tCKmin_X_ps,
+	       picos_to_mhz(plcd_dimm_params->tCKmin_X_ps));
+	printf("tCKmax_ps = %u (%u MHz)\n",
+	       plcd_dimm_params->tCKmax_ps,
+	       picos_to_mhz(plcd_dimm_params->tCKmax_ps));
+	printf("tCKmax_max_ps = %u\n", plcd_dimm_params->tCKmax_max_ps);
+
+	/* Basic timing parameters */
+	printf("tRCD_ps = %u\n", plcd_dimm_params->tRCD_ps);
+	printf("tRP_ps = %u\n", plcd_dimm_params->tRP_ps);
+	printf("tRAS_ps = %u\n", plcd_dimm_params->tRAS_ps);
+
+	/* maximum = 63750 ps */
+	printf("tWR_ps = %u\n", plcd_dimm_params->tWR_ps);
+
+	/* maximum = 63750 ps */
+	printf("tWTR_ps = %u\n", plcd_dimm_params->tWTR_ps);
+
+	/* maximum = 255 ns + 256 ns + .75 ns = 511750 ps */
+	printf("tRFC_ps = %u\n", plcd_dimm_params->tRFC_ps);
+
+	/* maximum = 63750 ps */
+	printf("tRRD_ps = %u\n", plcd_dimm_params->tRRD_ps);
+
+	/* maximum = 254 ns + .75 ns = 254750 ps */
+	printf("tRC_ps = %u\n", plcd_dimm_params->tRC_ps);
+
+	printf("refresh_rate_ps = %u\n", plcd_dimm_params->refresh_rate_ps);
+
+	/* byte 32, spd->ca_setup */
+	printf("tIS_ps = %u\n", plcd_dimm_params->tIS_ps);
+	/* byte 33, spd->ca_hold */
+	printf("tIH_ps = %u\n", plcd_dimm_params->tIH_ps);
+	/* byte 34, spd->data_setup */
+	printf("tDS_ps = %u\n", plcd_dimm_params->tDS_ps);
+	/* byte 35, spd->data_hold */
+	printf("tDH_ps = %u\n", plcd_dimm_params->tDH_ps);
+	/* byte 38, spd->trtp */
+	printf("tRTP_ps = %u\n", plcd_dimm_params->tRTP_ps);
+	/* byte 44, spd->tdqsq */
+	printf("tDQSQ_max_ps = %u\n", plcd_dimm_params->tDQSQ_max_ps);
+	/* byte 45, spd->tqhs */
+	printf("tQHS_ps = %u\n", plcd_dimm_params->tQHS_ps);
+
+	printf("lowest_common_SPD_caslat = %u\n",
+	       plcd_dimm_params->lowest_common_SPD_caslat);
+	printf("highest_common_derated_caslat = %u\n",
+	       plcd_dimm_params->highest_common_derated_caslat);
+	printf("additive_latency = %u\n", plcd_dimm_params->additive_latency);
+
+	printf("ndimms_present = %u\n", plcd_dimm_params->ndimms_present);
+	printf("all_DIMMs_burst_lengths_bitmask = %02X\n",
+	       plcd_dimm_params->all_DIMMs_burst_lengths_bitmask);
+	printf("all_DIMMs_registered = %u\n",
+	       plcd_dimm_params->all_DIMMs_registered);
+	printf("all_DIMMs_unbuffered = %u\n",
+	       plcd_dimm_params->all_DIMMs_unbuffered);
+	printf("all_DIMMs_ECC_capable = %u\n",
+	       plcd_dimm_params->all_DIMMs_ECC_capable);
+
+	printf("total_mem = %llu (%llu megabytes)\n",
+	       plcd_dimm_params->total_mem,
+	       plcd_dimm_params->total_mem / 0x100000);
+	printf("base_address = %llu (%llu megabytes)\n",
+	       plcd_dimm_params->base_address,
+	       plcd_dimm_params->base_address / 0x100000);
+}
+
+static void
+fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
+			   unsigned int ctl_num,
+			   const char *optname_str,
+			   const char *value_str)
+{
+	/*
+	 * This array all on the stack and *computed* each time this
+	 * function is rung.
+	 */
+	options_strings_uint_t options[] = {
+		{"memctl_interleaving",
+		 &pinfo->memctl_opts[ctl_num].memctl_interleaving},
+		{"memctl_interleaving_mode",
+		 &pinfo->memctl_opts[ctl_num].memctl_interleaving_mode},
+		{"ba_intlv_ctl",
+		 &pinfo->memctl_opts[ctl_num].ba_intlv_ctl},
+		{"ecc_mode", &pinfo->memctl_opts[ctl_num].ECC_mode},
+		{"ECC_mode", &pinfo->memctl_opts[ctl_num].ECC_mode},
+		{"self_refresh_in_sleep",
+		 &pinfo->memctl_opts[ctl_num].self_refresh_in_sleep},
+		{"dynamic_power",
+		 &pinfo->memctl_opts[ctl_num].dynamic_power},
+		{"data_bus_width",
+		 &pinfo->memctl_opts[ctl_num].data_bus_width},
+		{"burst_length",
+		 &pinfo->memctl_opts[ctl_num].burst_length},
+		{"cas_latency_override",
+		 &pinfo->memctl_opts[ctl_num].cas_latency_override},
+		{"cas_latency_override_value",
+		 &pinfo->memctl_opts[ctl_num].cas_latency_override_value},
+		{"use_derated_caslat",
+		 &pinfo->memctl_opts[ctl_num].use_derated_caslat},
+		{"additive_latency_override",
+		 &pinfo->memctl_opts[ctl_num].additive_latency_override},
+		{"additive_latency_override_value",
+		 &pinfo->memctl_opts[ctl_num].additive_latency_override_value},
+		{"clk_adjust", &pinfo->memctl_opts[ctl_num].clk_adjust},
+		{"cpo_override",
+		 &pinfo->memctl_opts[ctl_num].cpo_override},
+		{"write_data_delay",
+		 &pinfo->memctl_opts[ctl_num].write_data_delay},
+		{"half_strength_driver_enable",
+		 &pinfo->memctl_opts[ctl_num].half_strength_driver_enable},
+
+		/*
+		 * These can probably be changed to 2T_EN and 3T_EN
+		 * (using a leading numerical character) without problem
+		 */
+		{"twoT_en", &pinfo->memctl_opts[ctl_num].twoT_en},
+		{"threeT_en", &pinfo->memctl_opts[ctl_num].threeT_en},
+		{"bstopre", &pinfo->memctl_opts[ctl_num].bstopre},
+		{"tCKE_clock_pulse_width_ps",
+		 &pinfo->memctl_opts[ctl_num].tCKE_clock_pulse_width_ps},
+		{"tFAW_window_four_activates_ps",
+		 &pinfo->memctl_opts[ctl_num].tFAW_window_four_activates_ps}
+	};
+
+	const unsigned int nopts = ARRAY_SIZE(options);
+
+	if (handle_uint_option_table(options, nopts, optname_str, value_str))
+		return;
+
+	printf("couldn't find option string %s\n", optname_str);
+}
+
+static void
+print_fsl_memctl_config_regs(const fsl_memctl_config_regs_t *ddr)
+{
+	unsigned int i;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		printf("cs%u_bnds           = %08X\n", i, ddr->cs[i].bnds);
+		printf("cs%u_config         = %08X\n", i, ddr->cs[i].config);
+		printf("cs%u_config_2       = %08X\n", i, ddr->cs[i].config_2);
+	}
+
+	printf("timing_cfg_3       = %08X\n", ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\n", ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\n", ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\n", ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\n", ddr->ddr_sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\n", ddr->ddr_sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\n", ddr->ddr_sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\n", ddr->ddr_sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\n", ddr->ddr_sdram_interval);
+	printf("ddr_data_init      = %08X\n", ddr->ddr_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\n", ddr->ddr_sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\n", ddr->ddr_init_addr);
+	printf("ddr_init_ext_addr  = %08X\n", ddr->ddr_init_ext_addr);
+	printf("timing_cfg_4       = %08X\n", ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\n", ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\n", ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\n", ddr->ddr_wrlvl_cntl);
+	printf("ddr_pd_cntl        = %08X\n", ddr->ddr_pd_cntl);
+	printf("ddr_sr_cntr        = %08X\n", ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\n", ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\n", ddr->ddr_sdram_rcw_2);
+}
+
+static void
+fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
+			unsigned int ctrl_num,
+			const char *regname,
+			unsigned int value)
+{
+	unsigned int i;
+	fsl_memctl_config_regs_t *ddr;
+	char buf[20];
+
+	debug("fsl_ddr_regs_edit: ctrl_num = %u, "
+		"regname = %s, value = 0x%08X\n",
+		ctrl_num, regname, value);
+	if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS) {
+		return;
+	}
+
+	/* FIXME: Change this into struct like the other editing functions */
+	ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]);
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		sprintf(buf, "cs%u_bnds", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].bnds = value;
+			return;
+		}
+
+		sprintf(buf, "cs%u_config", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].config = value;
+			return;
+		}
+
+		sprintf(buf, "cs%u_config_2", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].config_2 = value;
+			return;
+		}
+	}
+
+	if (strcmp("timing_cfg_3", regname) == 0) {
+		ddr->timing_cfg_3 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_0", regname) == 0) {
+		ddr->timing_cfg_0 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_1", regname) == 0) {
+		ddr->timing_cfg_1 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_2", regname) == 0) {
+		ddr->timing_cfg_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_cfg", regname) == 0) {
+		ddr->ddr_sdram_cfg = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_cfg_2", regname) == 0) {
+		ddr->ddr_sdram_cfg_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode", regname) == 0) {
+		ddr->ddr_sdram_mode = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_2", regname) == 0) {
+		ddr->ddr_sdram_mode_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_interval", regname) == 0) {
+		ddr->ddr_sdram_interval = value;
+		return;
+	}
+
+	if (strcmp("ddr_data_init", regname) == 0) {
+		ddr->ddr_data_init = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_clk_cntl", regname) == 0) {
+		ddr->ddr_sdram_clk_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_init_addr", regname) == 0) {
+		ddr->ddr_init_addr = value;
+		return;
+	}
+
+	if (strcmp("ddr_init_ext_addr", regname) == 0) {
+		ddr->ddr_init_ext_addr = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_4", regname) == 0) {
+		ddr->timing_cfg_4 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_5", regname) == 0) {
+		ddr->timing_cfg_5 = value;
+		return;
+	}
+
+	if (strcmp("ddr_zq_cntl", regname) == 0) {
+		ddr->ddr_zq_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_wrlvl_cntl", regname) == 0) {
+		ddr->ddr_wrlvl_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_pd_cntl", regname) == 0) {
+		ddr->ddr_pd_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_sr_cntr", regname) == 0) {
+		ddr->ddr_sr_cntr = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_rcw_1", regname) == 0) {
+		ddr->ddr_sdram_rcw_1 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_rcw_2", regname) == 0) {
+		ddr->ddr_sdram_rcw_2 = value;
+		return;
+	}
+}
+
+static const char *
+get_sdram_type(unsigned int sdram_type)
+{
+	switch (sdram_type) {
+	case 2:
+		return "DDR1";
+	case 3:
+		return "DDR2";
+	case 6:
+		return "LPDDR1";
+	case 7:
+		return "DDR3";
+	}
+
+	return "unknown SDRAM type";
+}
+
+static void
+print_memctl_options(const memctl_options_t *popts)
+{
+	/* Special configurations for chip select */
+	printf("memctl_interleaving = %u\n", popts->memctl_interleaving);
+	printf("memctl_interleaving_mode = %u\n",
+	       popts->memctl_interleaving_mode);
+	printf("ba_intlv_ctl = 0x%02X\n", popts->ba_intlv_ctl);
+
+	/* Operational mode parameters */
+	/* 2 = DDR1, 3 = DDR2, 6 = LPDDR1, 7 = DDR3 */
+	printf("sdram_type = %u (%s)\n",
+	       popts->sdram_type, get_sdram_type(popts->sdram_type));
+
+	printf("ECC_mode = %u\n", popts->ECC_mode);	 /* Use ECC? */
+
+	/* Initialize ECC using memory controller? */
+	printf("ECC_init_using_memctl = %u\n", popts->ECC_init_using_memctl);
+
+	/* Use DQS? maybe only with DDR2? */
+	printf("DQS_config = %u\n", popts->DQS_config);
+
+	/* SREN - self-refresh during sleep */
+	printf("self_refresh_in_sleep = %u\n", popts->self_refresh_in_sleep);
+
+	/* DYN_PWR */
+	printf("dynamic_power = %u\n", popts->dynamic_power);
+
+	/* memory data width to use (16-bit, 32-bit, 64-bit) */
+	printf("data_bus_width = %u\n", popts->data_bus_width);
+
+	/* 4, 8 */
+	printf("burst_length = %u\n", popts->burst_length);
+
+	/* Global Timing Parameters */
+	printf("cas_latency_override = %u\n", popts->cas_latency_override);
+	printf("cas_latency_override_value = %u\n",
+	       popts->cas_latency_override_value);
+	printf("use_derated_caslat = %u\n", popts->use_derated_caslat);
+	printf("additive_latency_override = %u\n",
+	       popts->additive_latency_override);
+	printf("additive_latency_override_value = %u\n",
+	       popts->additive_latency_override_value);
+	printf("clk_adjust = %u\n", popts->clk_adjust);
+	printf("cpo_override = %u\n", popts->cpo_override);
+	/* DQS adjust */
+	printf("write_data_delay = %u\n", popts->write_data_delay);
+	printf("half_strength_driver_enable = %u\n",
+	       popts->half_strength_driver_enable);
+	printf("twoT_en = %u\n", popts->twoT_en);
+	printf("threeT_en = %u\n", popts->threeT_en);
+	printf("bstopre = %u\n", popts->bstopre);
+	/* tCKE */
+	printf("tCKE_clock_pulse_width_ps = %u\n",
+	       popts->tCKE_clock_pulse_width_ps);
+	/* tFAW --  FOUR_ACT */
+	printf("tFAW_window_four_activates_ps = %u\n",
+	       popts->tFAW_window_four_activates_ps);
+}
+
+static __inline__ void
+generic_spd_dump(const generic_spd_eeprom_t *spd)
+{
+#if defined(CONFIG_FSL_DDR1)
+	ddr1_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR2)
+	ddr2_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR3)
+#error "Implement generic_spd_dump() for DDR3"
+#endif
+}
+
+static void
+fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo,
+			unsigned int ctrl_mask,
+			unsigned int dimm_mask,
+			unsigned int do_mask)
+{
+	unsigned int i, j, retval;
+
+	/* STEP 1:  DIMM SPD data */
+	if (do_mask & STEP_GET_SPD) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+
+			/*
+			 * FIXME: find a way to make this generate more
+			 * optimal powerpc code (i.e. rlwimi.)
+			 */
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				if (!(dimm_mask & (1 << j)))
+					continue;
+
+				printf("SPD info:  Controller=%u "
+						"DIMM=%u\n", i, j);
+				generic_spd_dump(
+					&(pinfo->spd_installed_dimms[i][j]));
+				printf("\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 2:  DIMM Parameters */
+	if (do_mask & STEP_COMPUTE_DIMM_PARMS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				if (!(dimm_mask & (1 << j)))
+					continue;
+				printf("DIMM parameters:  Controller=%u "
+						"DIMM=%u\n", i, j);
+				print_dimm_parameters(
+					&(pinfo->dimm_params[i][j]));
+				printf("\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 3:  Common Parameters */
+	if (do_mask & STEP_COMPUTE_COMMON_PARMS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("\"lowest common\" DIMM parameters:  "
+					"Controller=%u\n", i);
+			print_lowest_common_dimm_parameters(
+				&pinfo->common_timing_params[i]);
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 4:  User Configuration Options */
+	if (do_mask & STEP_GATHER_OPTS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("User Config Options: Controller=%u\n", i);
+			print_memctl_options(&pinfo->memctl_opts[i]);
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 5:  Address assignment */
+	if (do_mask & STEP_ASSIGN_ADDRESSES) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				printf("Address Assignment: Controller=%u "
+						"DIMM=%u\n", i, j);
+				printf("Don't have this functionality yet\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 6:  computed controller register values */
+	if (do_mask & STEP_COMPUTE_REGS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("Computed Register Values: Controller=%u\n", i);
+			print_fsl_memctl_config_regs(
+				&pinfo->fsl_ddr_config_reg[i]);
+			retval = check_fsl_memctl_config_regs(
+				&pinfo->fsl_ddr_config_reg[i]);
+			if (retval) {
+				printf("check_fsl_memctl_config_regs "
+					"result = %u\n", retval);
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+}
+
+phys_size_t
+fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
+{
+	phys_size_t ddrsize;
+	const char *prompt = "FSL DDR>";
+	unsigned int len;
+	char buffer[CFG_CBSIZE];
+	char *argv[CFG_MAXARGS + 1];		/* NULL terminated */
+	int argc;
+	unsigned int next_step = STEP_GET_SPD;
+
+	/*
+	 * The strategy for next_step is that it points to the next
+	 * step in the computation process that needs to be done.
+	 */
+	while (1) {
+		/*
+		 * No need to worry for buffer overflow here in
+		 * this function;  readline() maxes out at CFG_CBSIZE
+		 */
+		len = readline_into_buffer(prompt,  buffer);
+		argc = parse_line(buffer, argv);
+		if (argc == 0) {
+			continue;
+		}
+
+		if (strcmp(argv[0], "help") == 0) {
+
+			/*
+			 * FIXME: For some reason printing this whole
+			 * thing causes the machine to freeze.
+			 * Splitting it into two printfs seems to make
+			 * it work Does printf() have limits on the
+			 * length of the string?
+			 */
+			printf(
+       "commands:\n"
+       "print      print SPD and intermediate computed data\n"
+       "reset      reboot machine\n"
+       "recompute  reload SPD and options to default and recompute regs\n");
+			printf(
+       "compute    recompute registers from current next_step to end\n"
+       "next_step  shows current next_step\n"
+       "help       this message\n"
+       "go         program the memory controller and continue with u-boot\n"
+	       );
+			continue;
+		}
+
+		if (strcmp(argv[0], "next_step") == 0) {
+			printf("next_step = 0x%02X (%s)\n",
+			       next_step,
+			       step_to_string(__ilog2(next_step)));
+			continue;
+		}
+
+		if (strcmp(argv[0], "edit") == 0) {
+			unsigned int i;
+			unsigned int error = 0;
+			unsigned int step_mask = 0;
+			unsigned int ctlr_mask = 0;
+			unsigned int dimm_mask = 0;
+			char *p_element = NULL;
+			char *p_value = NULL;
+			unsigned int dimm_number_required = 0;
+			unsigned int ctrl_num;
+			unsigned int dimm_num;
+
+			if (argc == 1) {
+				/* Only the element and value must be last */
+				printf("edit <c#> <d#> "
+					"<spd|dimmparms|commonparms|opts|"
+					"addresses|regs> <element> <value>\n");
+				continue;
+			}
+
+			for (i = 1; i < argc - 2; i++) {
+				if (strcmp(argv[i], "spd") == 0) {
+					step_mask |= STEP_GET_SPD;
+					dimm_number_required = 1;
+					continue;
+				}
+
+				if (strcmp(argv[i], "dimmparms") == 0) {
+					step_mask |= STEP_COMPUTE_DIMM_PARMS;
+					dimm_number_required = 1;
+					continue;
+				}
+
+				if (strcmp(argv[i], "commonparms") == 0) {
+					step_mask |= STEP_COMPUTE_COMMON_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "opts") == 0) {
+					step_mask |= STEP_GATHER_OPTS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "addresses") == 0) {
+					step_mask |= STEP_ASSIGN_ADDRESSES;
+					/*  FIXME: not done yet */
+					continue;
+				}
+
+				if (strcmp(argv[i], "regs") == 0) {
+					step_mask |= STEP_COMPUTE_REGS;
+					continue;
+				}
+
+				if (argv[i][0] == 'c') {
+					char c = argv[i][1];
+					if (isdigit(c)) {
+						ctlr_mask |= 1 << (c - '0');
+					}
+					continue;
+				}
+
+				if (argv[i][0] == 'd') {
+					char c = argv[i][1];
+					if (isdigit(c)) {
+						dimm_mask |= 1 << (c - '0');
+					}
+					continue;
+				}
+
+				printf("unknown arg %s\n", argv[i]);
+				step_mask = 0;
+				error = 1;
+				break;
+			}
+
+
+			if (error) {
+				continue;
+			}
+
+
+			/* Check arguments */
+
+			/* ERROR: If no steps were found */
+			if (step_mask == 0) {
+				printf("Error: No valid steps were specified "
+						" in argument.\n");
+				continue;
+			}
+
+			/* ERROR: If multiple steps were found */
+			if (step_mask & (step_mask - 1)) {
+				printf("Error: Multiple steps specified in "
+						"argument.\n");
+				continue;
+			}
+
+			/* ERROR: Controller not specified */
+			if (ctlr_mask == 0) {
+				printf("Error: controller number not "
+					"specified or no element and "
+					"value specified\n");
+				continue;
+			}
+
+			if (ctlr_mask & (ctlr_mask - 1)) {
+				printf("Error: multiple controllers "
+						"specified, %X\n", ctlr_mask);
+				continue;
+			}
+
+			/* ERROR: DIMM number not specified */
+			if (dimm_number_required && dimm_mask == 0) {
+				printf("Error: DIMM number number not "
+					"specified or no element and "
+					"value specified\n");
+				continue;
+			}
+
+			if (dimm_mask & (dimm_mask - 1)) {
+				printf("Error: multipled DIMMs specified\n");
+				continue;
+			}
+
+			p_element = argv[argc - 2];
+			p_value = argv[argc - 1];
+
+			ctrl_num = __ilog2(ctlr_mask);
+			dimm_num = __ilog2(dimm_mask);
+
+			switch (step_mask) {
+			case STEP_GET_SPD:
+				{
+					unsigned int element_num;
+					unsigned int value;
+
+					element_num = simple_strtoul(p_element,
+								     NULL, 0);
+					value = simple_strtoul(p_value,
+							       NULL, 0);
+					fsl_ddr_spd_edit(pinfo,
+							       ctrl_num,
+							       dimm_num,
+							       element_num,
+							       value);
+					next_step = STEP_COMPUTE_DIMM_PARMS;
+				}
+				break;
+
+			case STEP_COMPUTE_DIMM_PARMS:
+				fsl_ddr_dimm_parameters_edit(
+						 pinfo, ctrl_num, dimm_num,
+						 p_element, p_value);
+				next_step = STEP_COMPUTE_COMMON_PARMS;
+				break;
+
+			case STEP_COMPUTE_COMMON_PARMS:
+				lowest_common_dimm_parameters_edit(pinfo,
+						ctrl_num, p_element, p_value);
+				next_step = STEP_GATHER_OPTS;
+				break;
+
+			case STEP_GATHER_OPTS:
+				fsl_ddr_options_edit(pinfo, ctrl_num,
+							   p_element, p_value);
+				next_step = STEP_ASSIGN_ADDRESSES;
+				break;
+
+			case STEP_ASSIGN_ADDRESSES:
+				printf("editing of address assignment "
+						"not yet implemented\n");
+				break;
+
+			case STEP_COMPUTE_REGS:
+				{
+					unsigned int value;
+
+					value = simple_strtoul(p_value,
+							       NULL, 0);
+					fsl_ddr_regs_edit(pinfo,
+								ctrl_num,
+								p_element,
+								value);
+					next_step = STEP_PROGRAM_REGS;
+				}
+				break;
+
+			default:
+				printf("programming error\n");
+				while (1);
+				break;
+			}
+			continue;
+		}
+
+		if (strcmp(argv[0], "reset") == 0) {
+			/*
+			 * Reboot machine.
+			 * Args don't seem to matter because this
+			 * doesn't return
+			 */
+			do_reset(NULL, 0, 0, NULL);
+		}
+
+		if (strcmp(argv[0], "recompute") == 0) {
+			/*
+			 * Recalculate everything, starting with
+			 * loading SPD EEPROM from DIMMs
+			 */
+			next_step = STEP_GET_SPD;
+			ddrsize = fsl_ddr_compute(pinfo, next_step);
+			/*
+			 * FIXME: There some problems with this.
+			 * For exmaple, what happens if there is
+			 * an error inside fsl_ddr_compute?
+			 */
+			continue;
+		}
+
+		if (strcmp(argv[0], "compute") == 0) {
+			/*
+			 * Compute rest of steps starting at
+			 * the current next_step/
+			 */
+			ddrsize = fsl_ddr_compute(pinfo, next_step);
+			continue;
+		}
+
+		if (strcmp(argv[0], "print") == 0) {
+			unsigned int i;
+			unsigned int error = 0;
+			unsigned int step_mask = 0;
+			unsigned int ctlr_mask = 0;
+			unsigned int dimm_mask = 0;
+
+			if (argc == 1) {
+				printf("print [c<n>] [d<n>] [spd] [dimmparms] "
+				  "[commonparms] [opts] [addresses] [regs]\n");
+				continue;
+			}
+
+			for (i = 1; i < argc; i++) {
+				if (strcmp(argv[i], "spd") == 0) {
+					step_mask |= STEP_GET_SPD;
+					continue;
+				}
+
+				if (strcmp(argv[i], "dimmparms") == 0) {
+					step_mask |= STEP_COMPUTE_DIMM_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "commonparms") == 0) {
+					step_mask |= STEP_COMPUTE_COMMON_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "opts") == 0) {
+					step_mask |= STEP_GATHER_OPTS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "addresses") == 0) {
+					step_mask |= STEP_ASSIGN_ADDRESSES;
+					continue;
+				}
+
+				if (strcmp(argv[i], "regs") == 0) {
+					step_mask |= STEP_COMPUTE_REGS;
+					continue;
+				}
+
+				if (argv[i][0] == 'c') {
+					char c = argv[i][1];
+					if (isdigit(c)) {
+						ctlr_mask |= 1 << (c - '0');
+					}
+					continue;
+				}
+
+				if (argv[i][0] == 'd') {
+					char c = argv[i][1];
+					if (isdigit(c)) {
+						dimm_mask |= 1 << (c - '0');
+					}
+					continue;
+				}
+
+				printf("unknown arg %s\n", argv[i]);
+				step_mask = 0;
+				error = 1;
+				break;
+			}
+
+			if (error) {
+				continue;
+			}
+
+			/* If no particular controller was found, print all */
+			if (ctlr_mask == 0) {
+				ctlr_mask = 0xFF;
+			}
+
+			/* If no particular dimm was found, print all dimms. */
+			if (dimm_mask == 0) {
+				dimm_mask = 0xFF;
+			}
+
+			/* If no steps were found, print all steps. */
+			if (step_mask == 0) {
+				step_mask = STEP_ALL;
+			}
+
+			fsl_ddr_printinfo(pinfo, ctlr_mask,
+						dimm_mask, step_mask);
+			continue;
+		}
+
+		if (strcmp(argv[0], "go") == 0) {
+			if (next_step) {
+				ddrsize = fsl_ddr_compute(pinfo, next_step);
+			}
+			break;
+		}
+
+		printf("unknown command %s\n", argv[0]);
+	}
+
+	debug("end of memory = %llu\n", (u64)ddrsize);
+
+	return ddrsize;
+}
diff --git a/cpu/mpc8xxx/fsl_ddr_sdram.c b/cpu/mpc8xxx/fsl_ddr_sdram.c
index 0663609..c0b5dfd 100644
--- a/cpu/mpc8xxx/fsl_ddr_sdram.c
+++ b/cpu/mpc8xxx/fsl_ddr_sdram.c
@@ -84,7 +84,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
  *                              |  interleaving
  */
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined (CONFIG_FSL_DDR_INTERACTIVE)
 const char *step_string_tbl[] = {
 	"STEP_GET_SPD",
 	"STEP_COMPUTE_DIMM_PARMS",
@@ -1072,6 +1072,16 @@ phys_size_t fsl_ddr_sdram(void)
 	/* Compute it once normally. */
 	total_memory = fsl_ddr_compute(&info, STEP_GET_SPD);
 
+#ifdef CONFIG_FSL_DDR_INTERACTIVE
+	/*
+	 * The presence of the environment variable "ddrsetup"
+	 * causes the interactive DDR setup prompt to appear.
+	 */
+	if (getenv("ddrsetup")) {
+		total_memory = fsl_ddr_interactive(&info);
+	}
+#endif
+
 	/* Check for memory controller interleaving. */
 	memctl_interleaved = 0;
 	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
diff --git a/cpu/mpc8xxx/fsl_ddr_sdram.h b/cpu/mpc8xxx/fsl_ddr_sdram.h
index 58cac09..8823114 100644
--- a/cpu/mpc8xxx/fsl_ddr_sdram.h
+++ b/cpu/mpc8xxx/fsl_ddr_sdram.h
@@ -61,6 +61,9 @@ typedef struct {
 extern phys_size_t
 fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step);
 
+extern phys_size_t
+fsl_ddr_interactive(fsl_ddr_info_t *pinfo);
+
 extern const char * step_to_string(unsigned int step);
 /*
  * Compute steps
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar()
  2008-08-20 23:22       ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Kumar Gala
@ 2008-08-20 23:22         ` Kumar Gala
  2008-08-20 23:22           ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code Kumar Gala
  2008-08-26 23:10           ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Wolfgang Denk
  2008-08-26 23:09         ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Make fsl_ddr_sdram_set_lawbar() a weak function to allow board code to
override if desired.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/misc/fsl_law.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c
index 48ece4f..24a0340 100644
--- a/drivers/misc/fsl_law.c
+++ b/drivers/misc/fsl_law.c
@@ -121,6 +121,94 @@ void print_laws(void)
 	return;
 }
 
+#if defined(CONFIG_FSL_DDR1) || \
+    defined(CONFIG_FSL_DDR2) || \
+    defined(CONFIG_FSL_DDR3)
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+/* use up to 2 LAWs for DDR, used the last available LAWs */
+int __set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
+{
+	u64 start_align, law_sz;
+	int law_sz_enc;
+
+	if (start == 0)
+		start_align = 1ull << (LAW_SIZE_32G + 1);
+	else
+		start_align = 1ull << (ffs64(start) - 1);
+	law_sz = min(start_align, sz);
+	law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+	if (set_last_law(start, law_sz_enc, id) < 0)
+		return -1;
+
+	/* do we still have anything to map */
+	sz = sz - law_sz;
+	if (sz) {
+		start += law_sz;
+
+		start_align = 1ull << (ffs64(start) - 1);
+		law_sz = min(start_align, sz);
+		law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+		if (set_last_law(start, law_sz_enc, id) < 0)
+			return -1;
+	} else {
+		return 0;
+	}
+
+	/* do we still have anything to map */
+	sz = sz - law_sz;
+	if (sz)
+		return 1;
+
+	return 0;
+}
+
+void
+__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+			   unsigned int memctl_interleaved,
+			   unsigned int ctrl_num)
+{
+	/*
+	 * If no DIMMs on this controller, do not proceed any further.
+	 */
+	if (!memctl_common_params->ndimms_present) {
+		return;
+	}
+
+	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(memctl_common_params->base_address,
+				memctl_common_params->total_mem,
+				lawbar1_target_id) < 0) {
+			printf("ERROR\n");
+			return ;
+		}
+	} else if (ctrl_num == 1) {
+		if (__set_ddr_laws(memctl_common_params->base_address,
+				memctl_common_params->total_mem,
+				LAW_TRGT_IF_DDR_2) < 0) {
+			printf("ERROR\n");
+			return ;
+		}
+	} else {
+		printf("unexpected controller number %u in %s\n",
+			ctrl_num, __FUNCTION__);
+	}
+}
+
+__attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void
+fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+			 unsigned int memctl_interleaved,
+			 unsigned int ctrl_num);
+#endif
+
 void init_laws(void)
 {
 	int i;
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code
  2008-08-20 23:22         ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Kumar Gala
@ 2008-08-20 23:22           ` Kumar Gala
  2008-08-20 23:22             ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new " Kumar Gala
  2008-08-26 23:10             ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for " Wolfgang Denk
  2008-08-26 23:10           ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Provide a helper function that board code can call to map TLBs when
setting up DDR.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 cpu/mpc85xx/tlb.c     |   64 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-ppc/mmu.h |    1 +
 2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/cpu/mpc85xx/tlb.c b/cpu/mpc85xx/tlb.c
index 3d15d50..7ce7a14 100644
--- a/cpu/mpc85xx/tlb.c
+++ b/cpu/mpc85xx/tlb.c
@@ -90,3 +90,67 @@ void init_tlbs(void)
 
 	return ;
 }
+
+unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+	unsigned int tlb_size;
+	unsigned int ram_tlb_index;
+	unsigned int ram_tlb_address;
+
+	/*
+	 * Determine size of each TLB1 entry.
+	 */
+	switch (memsize_in_meg) {
+	case 16:
+	case 32:
+		tlb_size = BOOKE_PAGESZ_16M;
+		break;
+	case 64:
+	case 128:
+		tlb_size = BOOKE_PAGESZ_64M;
+		break;
+	case 256:
+	case 512:
+		tlb_size = BOOKE_PAGESZ_256M;
+		break;
+	case 1024:
+	case 2048:
+		if (PVR_VER(get_pvr()) > PVR_VER(PVR_85xx))
+			tlb_size = BOOKE_PAGESZ_1G;
+		else
+			tlb_size = BOOKE_PAGESZ_256M;
+		break;
+	default:
+		puts("DDR: only 16M, 32M, 64M, 128M, 256M, 512M, 1G"
+			" and 2G are supported.\n");
+
+		/*
+		 * The memory was not able to be mapped.
+		 * Default to a small size.
+		 */
+		tlb_size = BOOKE_PAGESZ_64M;
+		memsize_in_meg = 64;
+		break;
+	}
+
+	/*
+	 * Configure DDR TLB1 entries.
+	 * Starting at TLB1 8, use no more than 8 TLB1 entries.
+	 */
+	ram_tlb_index = 8;
+	ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;
+	while (ram_tlb_address < (memsize_in_meg * 1024 * 1024)
+	      && ram_tlb_index < 16) {
+		set_tlb(1, ram_tlb_address, ram_tlb_address,
+			MAS3_SX|MAS3_SW|MAS3_SR, 0,
+			0, ram_tlb_index, tlb_size, 1);
+
+		ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));
+		ram_tlb_index++;
+	}
+
+	/*
+	 * Confirm that the requested amount of memory was mapped.
+	 */
+	return memsize_in_meg;
+}
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index 050a7b6..8975e6c 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -431,6 +431,7 @@ extern void set_tlb(u8 tlb, u32 epn, u64 rpn,
 extern void disable_tlb(u8 esel);
 extern void invalidate_tlb(u8 tlb);
 extern void init_tlbs(void);
+extern unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg);
 
 #define SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz, _iprot) \
 	{ .tlb = _tlb, .epn = _epn, .rpn = _rpn, .perms = _perms, \
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new DDR code.
  2008-08-20 23:22           ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code Kumar Gala
@ 2008-08-20 23:22             ` Kumar Gala
  2008-08-20 23:22               ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Kumar Gala
  2008-08-26 23:11               ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN " Wolfgang Denk
  2008-08-26 23:10             ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 Makefile                                  |    3 +
 board/freescale/mpc8641hpcn/Makefile      |    8 +-
 board/freescale/mpc8641hpcn/ddr.c         |  234 +++++++++++++++++++++++++++++
 board/freescale/mpc8641hpcn/mpc8641hpcn.c |    5 +-
 cpu/mpc86xx/Makefile                      |    1 -
 include/configs/MPC8641HPCN.h             |  117 ++++++++-------
 6 files changed, 307 insertions(+), 61 deletions(-)
 create mode 100644 board/freescale/mpc8641hpcn/ddr.c

diff --git a/Makefile b/Makefile
index 24700f9..7da88dc 100644
--- a/Makefile
+++ b/Makefile
@@ -237,6 +237,9 @@ endif
 ifeq ($(CPU),mpc85xx)
 LIBS += drivers/qe/qe.a
 endif
+ifeq ($(CPU),mpc86xx)
+LIBS += cpu/mpc8xxx/libmpc8xxx.a
+endif
 LIBS += drivers/rtc/librtc.a
 LIBS += drivers/serial/libserial.a
 LIBS += drivers/usb/libusb.a
diff --git a/board/freescale/mpc8641hpcn/Makefile b/board/freescale/mpc8641hpcn/Makefile
index c096e15..27d20a0 100644
--- a/board/freescale/mpc8641hpcn/Makefile
+++ b/board/freescale/mpc8641hpcn/Makefile
@@ -25,10 +25,12 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o law.o
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= law.o
+COBJS-y	+= ddr.o
 
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
diff --git a/board/freescale/mpc8641hpcn/ddr.c b/board/freescale/mpc8641hpcn/ddr.c
new file mode 100644
index 0000000..127c05b
--- /dev/null
+++ b/board/freescale/mpc8641hpcn/ddr.c
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+static void
+get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_bus_freq(0);
+}
+
+void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		if (ctrl_num == 0 && i == 1) {
+			i2c_address = SPD_EEPROM_ADDRESS2;
+		}
+		if (ctrl_num == 1 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS3;
+		}
+		if (ctrl_num == 1 && i == 1) {
+			i2c_address = SPD_EEPROM_ADDRESS4;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void
+fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC86xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC86xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+
+		if (i == 0) {
+			bnds = ddr->cs0_bnds;
+			config = ddr->cs0_config;
+
+		} else if (i == 1) {
+			bnds = ddr->cs1_bnds;
+			config = ddr->cs1_config;
+
+		} else if (i == 2) {
+			bnds = ddr->cs2_bnds;
+			config = ddr->cs2_config;
+
+		} else {
+			bnds = ddr->cs3_bnds;
+			config = ddr->cs3_config;
+		}
+
+		printf("cs%u_bnds           = %08X\n", i, bnds);
+		printf("cs%u_config         = %08X\n", i, config);
+	}
+
+	printf("timing_cfg_3       = %08X\n", ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\n", ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\n", ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\n", ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\n", ddr->sdram_cfg_1);
+	printf("ddr_sdram_cfg_2    = %08X\n", ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\n", ddr->sdram_mode_1);
+	printf("ddr_sdram_mode_2   = %08X\n", ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\n", ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\n", ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\n", ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\n", ddr->init_addr);
+}
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC86xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC86xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+		}
+	}
+
+	/* Someone decided to use different names from the documentation... */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode_1       = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC? Need to program err_disable, err_sbe, and err_int_en */
+	debug("before go\n");
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg_1 = regs->ddr_sdram_cfg;
+
+	/*
+	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done
+	 */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR2;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 7;
+}
+
+/*
+ * factors to consider for CPO:
+ * 	- frequency
+ * 	- ddr1 vs. ddr2
+ *
+ * FIXME: figure out how to compute or tabulate good values for this
+ */
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 10;
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8641hpcn/mpc8641hpcn.c b/board/freescale/mpc8641hpcn/mpc8641hpcn.c
index db46953..96bb908 100644
--- a/board/freescale/mpc8641hpcn/mpc8641hpcn.c
+++ b/board/freescale/mpc8641hpcn/mpc8641hpcn.c
@@ -25,18 +25,17 @@
 #include <asm/processor.h>
 #include <asm/immap_86xx.h>
 #include <asm/immap_fsl_pci.h>
-#include <spd_sdram.h>
 #include <asm/io.h>
 #include <libfdt.h>
 #include <fdt_support.h>
 
 #include "../common/pixis.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
 #endif
 
-void sdram_init(void);
 long int fixed_sdram(void);
 
 
@@ -61,7 +60,7 @@ initdram(int board_type)
 	long dram_size = 0;
 
 #if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram();
+	dram_size = fsl_ddr_sdram();
 #else
 	dram_size = fixed_sdram();
 #endif
diff --git a/cpu/mpc86xx/Makefile b/cpu/mpc86xx/Makefile
index 4227053..454c728 100644
--- a/cpu/mpc86xx/Makefile
+++ b/cpu/mpc86xx/Makefile
@@ -36,7 +36,6 @@ COBJS-y	+= cpu.o
 COBJS-y	+= cpu_init.o
 COBJS-y	+= speed.o
 COBJS-y	+= interrupts.o
-COBJS-y	+= spd_sdram.o
 
 COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
 
diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h
index 468fd08..e013e70 100644
--- a/include/configs/MPC8641HPCN.h
+++ b/include/configs/MPC8641HPCN.h
@@ -54,19 +54,6 @@
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
 
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#undef CONFIG_DDR_DLL			/* possible DLL fix needed */
-#define CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-#define CONFIG_NUM_DDR_CONTROLLERS     2
-/* #define CONFIG_DDR_INTERLEAVE	       1 */
-#define CACHE_LINE_INTERLEAVING		0x20000000
-#define PAGE_INTERLEAVING		0x21000000
-#define BANK_INTERLEAVING		0x22000000
-#define SUPER_BANK_INTERLEAVING		0x23000000
-
 #define CONFIG_HIGH_BATS	1	/* High BATs supported and enabled */
 
 #define CONFIG_ALTIVEC		1
@@ -104,53 +91,75 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR2
+#undef CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup */
+#define CONFIG_DDR_SPD
+
+#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
+#define CONFIG_MEM_INIT_VALUE	0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 #define CONFIG_VERY_BIG_RAM
 
 #define MPC86xx_DDR_SDRAM_CLK_CNTL
 
-#if defined(CONFIG_SPD_EEPROM)
-    /*
-     * Determine DDR configuration from I2C interface.
-     */
-    #define SPD_EEPROM_ADDRESS1		0x51		/* DDR DIMM */
-    #define SPD_EEPROM_ADDRESS2		0x52		/* DDR DIMM */
-    #define SPD_EEPROM_ADDRESS3		0x53		/* DDR DIMM */
-    #define SPD_EEPROM_ADDRESS4		0x54		/* DDR DIMM */
 
-#else
-    /*
-     * Manually set up DDR1 parameters
-     */
-
-    #define CFG_SDRAM_SIZE	256		/* DDR is 256MB */
-
-    #define CFG_DDR_CS0_BNDS	0x0000000F
-    #define CFG_DDR_CS0_CONFIG	0x80010102	/* Enable, no interleaving */
-    #define CFG_DDR_EXT_REFRESH 0x00000000
-    #define CFG_DDR_TIMING_0	0x00260802
-    #define CFG_DDR_TIMING_1	0x39357322
-    #define CFG_DDR_TIMING_2	0x14904cc8
-    #define CFG_DDR_MODE_1	0x00480432
-    #define CFG_DDR_MODE_2	0x00000000
-    #define CFG_DDR_INTERVAL	0x06090100
-    #define CFG_DDR_DATA_INIT	0xdeadbeef
-    #define CFG_DDR_CLK_CTRL	0x03800000
-    #define CFG_DDR_OCD_CTRL	0x00000000
-    #define CFG_DDR_OCD_STATUS	0x00000000
-    #define CFG_DDR_CONTROL	0xe3008000	/* Type = DDR2 */
-    #define CFG_DDR_CONTROL2	0x04400000
-
-    /* Not used in fixed_sdram function */
-
-    #define CFG_DDR_MODE	0x00000022
-    #define CFG_DDR_CS1_BNDS	0x00000000
-    #define CFG_DDR_CS2_BNDS	0x00000FFF	/* Not done */
-    #define CFG_DDR_CS3_BNDS	0x00000FFF	/* Not done */
-    #define CFG_DDR_CS4_BNDS	0x00000FFF	/* Not done */
-    #define CFG_DDR_CS5_BNDS	0x00000FFF	/* Not done */
-#endif
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	2
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	2
+
+/*
+ * Number of chip selects per memory controller
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+#define SPD_EEPROM_ADDRESS2	0x52	/* CTLR 0 DIMM 1 */
+#define SPD_EEPROM_ADDRESS3	0x53	/* CTLR 1 DIMM 0 */
+#define SPD_EEPROM_ADDRESS4	0x54	/* CTLR 1 DIMM 1 */
+
+
+/*
+ * These are used when DDR doesn't use SPD.
+ */
+#define CFG_SDRAM_SIZE		256		/* DDR is 256MB */
+#define CFG_DDR_CS0_BNDS	0x0000000F
+#define CFG_DDR_CS0_CONFIG	0x80010102      /* Enable, no interleaving */
+#define CFG_DDR_TIMING_3	0x00000000
+#define CFG_DDR_TIMING_0	0x00260802
+#define CFG_DDR_TIMING_1	0x39357322
+#define CFG_DDR_TIMING_2	0x14904cc8
+#define CFG_DDR_MODE_1		0x00480432
+#define CFG_DDR_MODE_2		0x00000000
+#define CFG_DDR_INTERVAL	0x06090100
+#define CFG_DDR_DATA_INIT	0xdeadbeef
+#define CFG_DDR_CLK_CTRL	0x03800000
+#define CFG_DDR_OCD_CTRL	0x00000000
+#define CFG_DDR_OCD_STATUS	0x00000000
+#define CFG_DDR_CONTROL		0xe3008000	/* Type = DDR2 */
+#define CFG_DDR_CONTROL2	0x04400000
+
+/*
+ * FIXME: Not used in fixed_sdram function
+ */
+#define CFG_DDR_MODE		0x00000022
+#define CFG_DDR_CS1_BNDS	0x00000000
+#define CFG_DDR_CS2_BNDS	0x00000FFF	/* Not done */
+#define CFG_DDR_CS3_BNDS	0x00000FFF	/* Not done */
+#define CFG_DDR_CS4_BNDS	0x00000FFF	/* Not done */
+#define CFG_DDR_CS5_BNDS	0x00000FFF	/* Not done */
+
 
 #define CONFIG_ID_EEPROM
 #define CFG_I2C_EEPROM_NXID
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD to new DDR code.
  2008-08-20 23:22             ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new " Kumar Gala
@ 2008-08-20 23:22               ` Kumar Gala
  2008-08-20 23:22                 ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Kumar Gala
  2008-08-26 23:11                 ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Wolfgang Denk
  2008-08-26 23:11               ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8610hpcd/Makefile      |   10 +-
 board/freescale/mpc8610hpcd/ddr.c         |  223 +++++++++++++++++++++++++++++
 board/freescale/mpc8610hpcd/mpc8610hpcd.c |    3 +-
 include/configs/MPC8610HPCD.h             |   50 +++++--
 4 files changed, 264 insertions(+), 22 deletions(-)
 create mode 100644 board/freescale/mpc8610hpcd/ddr.c

diff --git a/board/freescale/mpc8610hpcd/Makefile b/board/freescale/mpc8610hpcd/Makefile
index a457c32..dc97c33 100644
--- a/board/freescale/mpc8610hpcd/Makefile
+++ b/board/freescale/mpc8610hpcd/Makefile
@@ -23,14 +23,14 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o law.o
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
 
 COBJS-${CONFIG_FSL_DIU_FB}	+= mpc8610hpcd_diu.o
 
-COBJS	+= ${COBJS-y}
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
diff --git a/board/freescale/mpc8610hpcd/ddr.c b/board/freescale/mpc8610hpcd/ddr.c
new file mode 100644
index 0000000..fca2918
--- /dev/null
+++ b/board/freescale/mpc8610hpcd/ddr.c
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+static void
+get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_bus_freq(0);
+}
+
+
+void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC86xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC86xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+
+		if (i == 0) {
+			bnds = ddr->cs0_bnds;
+			config = ddr->cs0_config;
+
+		} else if (i == 1) {
+			bnds = ddr->cs1_bnds;
+			config = ddr->cs1_config;
+
+		} else if (i == 2) {
+			bnds = ddr->cs2_bnds;
+			config = ddr->cs2_config;
+
+		} else {
+			bnds = ddr->cs3_bnds;
+			config = ddr->cs3_config;
+
+		}
+
+		printf("cs%u_bnds           = %08X\n", i, bnds);
+		printf("cs%u_config         = %08X\n", i, config);
+	}
+
+	printf("timing_cfg_3       = %08X\n", ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\n", ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\n", ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\n", ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\n", ddr->sdram_cfg_1);
+	printf("ddr_sdram_cfg_2    = %08X\n", ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\n", ddr->sdram_mode_1);
+	printf("ddr_sdram_mode_2   = %08X\n", ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\n", ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\n", ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\n", ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\n", ddr->init_addr);
+}
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC86xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC86xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+		}
+	}
+
+	/* Someone decided to use different names from the documentation... */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode_1       = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en */
+	printf("before go\n");
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg_1 = regs->ddr_sdram_cfg;
+
+	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR2;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 7;
+}
+
+/*
+ * factors to consider for CPO:
+ * 	- frequency
+ * 	- ddr1 vs. ddr2
+ *
+ * FIXME: figure out how to compute or tabulate good values for this
+ */
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 10;
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd.c b/board/freescale/mpc8610hpcd/mpc8610hpcd.c
index ff1b892..34f845e 100644
--- a/board/freescale/mpc8610hpcd/mpc8610hpcd.c
+++ b/board/freescale/mpc8610hpcd/mpc8610hpcd.c
@@ -33,6 +33,7 @@
 #include <spd_sdram.h>
 
 #include "../common/pixis.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
@@ -122,7 +123,7 @@ initdram(int board_type)
 	long dram_size = 0;
 
 #if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram();
+	dram_size = fsl_ddr_sdram();
 #else
 	dram_size = fixed_sdram();
 #endif
diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h
index e9371a2..e8d80b1 100644
--- a/include/configs/MPC8610HPCD.h
+++ b/include/configs/MPC8610HPCD.h
@@ -8,7 +8,6 @@
 
 /*
  * MPC8610HPCD board configuration file
- *
  */
 
 #ifndef __CONFIG_H
@@ -45,14 +44,6 @@
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 #define CONFIG_ENV_OVERWRITE
-
-#define CONFIG_SPD_EEPROM		/* Use SPD for DDR */
-#undef CONFIG_DDR_DLL			/* possible DLL fix needed */
-#define CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-#undef  CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-#define CONFIG_NUM_DDR_CONTROLLERS	1
 #define CONFIG_INTERRUPTS		/* enable pci, srio, ddr interrupts */
 
 #define CONFIG_HIGH_BATS	1	/* High BATs supported & enabled */
@@ -92,22 +83,46 @@
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR2
+#undef CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SPD_EEPROM		/* Use SPD for DDR */
+#define CONFIG_DDR_SPD
+
+#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
+#define CONFIG_MEM_INIT_VALUE	0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 #define CONFIG_VERY_BIG_RAM
 
 #define MPC86xx_DDR_SDRAM_CLK_CNTL
 
-#if defined(CONFIG_SPD_EEPROM)
+
 /*
- * Determine DDR configuration from I2C interface.
+ * Number of memory controllers on device
  */
-#define SPD_EEPROM_ADDRESS1		0x51		/* DDR DIMM */
-#else
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
 /*
- * Manually set up DDR1 parameters
+ * Number of chip selects per memory controller
  */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
 
+/*
+ * These are used when DDR doesn't use SPD.
+ */
 #define CFG_SDRAM_SIZE	256		/* DDR is 256MB */
 
 #if 0 /* TODO */
@@ -130,7 +145,10 @@
 #define CFG_DDR_ERR_INT_EN	0x00000000
 #define CFG_DDR_ERR_DIS		0x00000000
 #define CFG_DDR_SBE		0x000f0000
- /* Not used in fixed_sdram function */
+
+/*
+ * FIXME: Not used in fixed_sdram function
+ */
 #define CFG_DDR_MODE		0x00000022
 #define CFG_DDR_CS1_BNDS	0x00000000
 #define CFG_DDR_CS2_BNDS	0x00000FFF	/* Not done */
@@ -138,7 +156,7 @@
 #define CFG_DDR_CS4_BNDS	0x00000FFF	/* Not done */
 #define CFG_DDR_CS5_BNDS	0x00000FFF	/* Not done */
 #endif
-#endif
+
 
 #define CONFIG_ID_EEPROM
 #define CFG_I2C_EEPROM_NXID
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS to new DDR code.
  2008-08-20 23:22               ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Kumar Gala
@ 2008-08-20 23:22                 ` Kumar Gala
  2008-08-20 23:22                   ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Kumar Gala
  2008-08-26 23:11                   ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Wolfgang Denk
  2008-08-26 23:11                 ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 Makefile                              |    1 +
 board/freescale/mpc8544ds/Makefile    |    9 +-
 board/freescale/mpc8544ds/ddr.c       |  242 +++++++++++++++++++++++++++++++++
 board/freescale/mpc8544ds/mpc8544ds.c |   11 +-
 cpu/mpc85xx/Makefile                  |    2 +-
 include/configs/MPC8544DS.h           |   52 ++++++--
 6 files changed, 298 insertions(+), 19 deletions(-)
 create mode 100644 board/freescale/mpc8544ds/ddr.c

diff --git a/Makefile b/Makefile
index 7da88dc..65ca5e2 100644
--- a/Makefile
+++ b/Makefile
@@ -236,6 +236,7 @@ LIBS += drivers/qe/qe.a
 endif
 ifeq ($(CPU),mpc85xx)
 LIBS += drivers/qe/qe.a
+LIBS += cpu/mpc8xxx/libmpc8xxx.a
 endif
 ifeq ($(CPU),mpc86xx)
 LIBS += cpu/mpc8xxx/libmpc8xxx.a
diff --git a/board/freescale/mpc8544ds/Makefile b/board/freescale/mpc8544ds/Makefile
index 3a5ea00..3997994 100644
--- a/board/freescale/mpc8544ds/Makefile
+++ b/board/freescale/mpc8544ds/Makefile
@@ -26,10 +26,13 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o law.o tlb.o
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
 
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
diff --git a/board/freescale/mpc8544ds/ddr.c b/board/freescale/mpc8544ds/ddr.c
new file mode 100644
index 0000000..d3e0ca8
--- /dev/null
+++ b/board/freescale/mpc8544ds/ddr.c
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+
+static void
+get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+
+void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		get_spd(&(ctrl_dimms_spd[i]), SPD_EEPROM_ADDRESS1);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_md_cntl  = %08X\t%p\n",
+		ddr->sdram_md_cntl, &ddr->sdram_md_cntl);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+}
+
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en */
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR2;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 7;
+}
+
+/*
+ * factors to consider for CPO:
+ * 	- frequency
+ * 	- ddr1 vs. ddr2
+ *
+ * FIXME: figure out how to compute or tabulate good values for this
+ */
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 10;
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8544ds/mpc8544ds.c b/board/freescale/mpc8544ds/mpc8544ds.c
index c39ce11..213539e 100644
--- a/board/freescale/mpc8544ds/mpc8544ds.c
+++ b/board/freescale/mpc8544ds/mpc8544ds.c
@@ -24,22 +24,21 @@
 #include <command.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <asm/immap_fsl_pci.h>
 #include <asm/io.h>
-#include <spd_sdram.h>
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
 
 #include "../common/pixis.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
 #endif
 
-void sdram_init(void);
-
 int checkboard (void)
 {
 	volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR);
@@ -69,7 +68,11 @@ initdram(int board_type)
 
 	puts("Initializing\n");
 
-	dram_size = spd_sdram();
+	dram_size = fsl_ddr_sdram();
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/*
diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile
index c180dbd..d51a6dd 100644
--- a/cpu/mpc85xx/Makefile
+++ b/cpu/mpc85xx/Makefile
@@ -43,7 +43,7 @@ endif
 endif
 
 COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o tlb.o \
-	  pci.o serial_scc.o commproc.o ether_fcc.o spd_sdram.o qe_io.o \
+	  pci.o serial_scc.o commproc.o ether_fcc.o qe_io.o \
 	  $(COBJS-y)
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h
index 9a77b7b..8feda9b 100644
--- a/include/configs/MPC8544DS.h
+++ b/include/configs/MPC8544DS.h
@@ -46,15 +46,6 @@
 
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup */
-#undef CONFIG_DDR_DLL
-#define CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-
-#define CONFIG_DDR_ECC_CMD
 #define CONFIG_INTERRUPTS		/* enable pci, srio, ddr interrupts */
 
 /*
@@ -64,8 +55,6 @@
  */
 #define CONFIG_ASSUME_AMD_FLASH
 
-#define MPC85xx_DDR_SDRAM_CLK_CNTL	/* 85xx has clock control reg */
-
 #ifndef __ASSEMBLY__
 extern unsigned long get_board_sys_clk(unsigned long dummy);
 #endif
@@ -104,6 +93,44 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR2
+#undef CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup */
+#define CONFIG_DDR_SPD
+
+#undef CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
+#define CONFIG_MEM_INIT_VALUE	0xDeadBeef
+
+#define CFG_DDR_SDRAM_BASE	0x00000000
+#define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
+#define CONFIG_VERY_BIG_RAM
+
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8544 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8544DS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	2
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
@@ -242,6 +269,9 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_STRTOUL		1
+#define CFG_64BIT_VSPRINTF		1
+
 /* I2C */
 #define CONFIG_FSL_I2C		/* Use FSL common I2C driver */
 #define CONFIG_HARD_I2C		/* I2C with hardware support */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS to new DDR code.
  2008-08-20 23:22                 ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Kumar Gala
@ 2008-08-20 23:22                   ` Kumar Gala
  2008-08-20 23:22                     ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Kumar Gala
  2008-08-26 23:12                     ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Wolfgang Denk
  2008-08-26 23:11                   ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8540ads/Makefile     |   13 +-
 board/freescale/mpc8540ads/ddr.c        |  282 +++++++++++++++++++++++++++++++
 board/freescale/mpc8540ads/mpc8540ads.c |   16 ++-
 include/configs/MPC8540ADS.h            |   70 +++++---
 4 files changed, 346 insertions(+), 35 deletions(-)
 create mode 100644 board/freescale/mpc8540ads/ddr.c

diff --git a/board/freescale/mpc8540ads/Makefile b/board/freescale/mpc8540ads/Makefile
index 2d71cbc..4c6da4d 100644
--- a/board/freescale/mpc8540ads/Makefile
+++ b/board/freescale/mpc8540ads/Makefile
@@ -25,11 +25,14 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o law.o tlb.o
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
-SOBJS	:= $(addprefix $(obj),$(SOBJS))
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS-y))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
 	$(AR) $(ARFLAGS) $@ $(OBJS)
diff --git a/board/freescale/mpc8540ads/ddr.c b/board/freescale/mpc8540ads/ddr.c
new file mode 100644
index 0000000..ab59bf6
--- /dev/null
+++ b/board/freescale/mpc8540ads/ddr.c
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+
+static void
+get_spd(ddr1_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr1_spd_eeprom_t));
+}
+
+
+unsigned int
+fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+
+void
+fsl_ddr_get_spd(ddr1_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void
+fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int config_2 = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+		unsigned int *pconfig_2 = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			config_2 = ddr->cs0_config_2;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+			pconfig_2= (unsigned int *)&ddr->cs0_config_2;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			config_2 = ddr->cs1_config_2;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+			pconfig_2= (unsigned int *)&ddr->cs1_config_2;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			config_2 = ddr->cs2_config_2;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+			pconfig_2= (unsigned int *)&ddr->cs2_config_2;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			config_2 = ddr->cs3_config_2;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+			pconfig_2= (unsigned int *) &ddr->cs3_config_2;
+
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+		printf("cs%u_config_2       = %08X\t%p\n",
+		       i, config_2, pconfig_2);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+
+	printf("timing_cfg_4       = %08X\t%p\n",
+		ddr->timing_cfg_4, &ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\t%p\n",
+		ddr->timing_cfg_5, &ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\t%p\n",
+		ddr->ddr_zq_cntl, &ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\t%p\n",
+		ddr->ddr_wrlvl_cntl, &ddr->ddr_wrlvl_cntl);
+	printf("ddr_pd_cntl        = %08X\t%p\n",
+		ddr->ddr_pd_cntl, &ddr->ddr_pd_cntl);
+	printf("ddr_sr_cntr        = %08X\t%p\n",
+		ddr->ddr_sr_cntr, &ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_1, &ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_2, &ddr->ddr_sdram_rcw_2);
+
+	printf("debug_1            = %08X\t%p\n",
+	       ddr->debug_1, &ddr->debug_1);
+}
+
+void
+fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+			ddr->cs0_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+			ddr->cs1_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+			ddr->cs2_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+			ddr->cs3_config_2 = regs->cs[i].config_2;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/*
+	 * FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en
+	 */
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	asm("sync;isync;msync");
+	udelay(500);
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR1;
+}
+
+/*
+ * Technically, the memory controller on this part doesn't even
+ * have the clk_adjust field for lack of the SDRAM_CLK_CNTL register.
+ */
+
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 0;
+}
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 0;	/* Should be 0 for DDR1 */
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8540ads/mpc8540ads.c b/board/freescale/mpc8540ads/mpc8540ads.c
index 4f068cc..926d9a6 100644
--- a/board/freescale/mpc8540ads/mpc8540ads.c
+++ b/board/freescale/mpc8540ads/mpc8540ads.c
@@ -28,11 +28,13 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
-#include <spd_sdram.h>
 #include <libfdt.h>
 #include <fdt_support.h>
 
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
+
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
 #endif
@@ -82,10 +84,16 @@ initdram(int board_type)
 	}
 #endif
 
-#if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram ();
+#ifdef CONFIG_SPD_EEPROM
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 #else
-	dram_size = fixed_sdram ();
+	dram_size = fixed_sdram();
 #endif
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
diff --git a/include/configs/MPC8540ADS.h b/include/configs/MPC8540ADS.h
index 6351925..4c10171 100644
--- a/include/configs/MPC8540ADS.h
+++ b/include/configs/MPC8540ADS.h
@@ -48,13 +48,6 @@
 #define CONFIG_PCI
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-#define CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 /*
@@ -104,28 +97,53 @@
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR1
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#undef CONFIG_FSL_DDR_INTERACTIVE
+
+#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#if defined(CONFIG_SPD_EEPROM)
-    /*
-     * Determine DDR configuration from I2C interface.
-     */
-    #define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
 
-#else
-    /*
-     * Manually set up DDR parameters
-     */
-    #define CFG_SDRAM_SIZE	128		/* DDR is 128MB */
-    #define CFG_DDR_CS0_BNDS	0x00000007	/* 0-128MB */
-    #define CFG_DDR_CS0_CONFIG	0x80000002
-    #define CFG_DDR_TIMING_1	0x37344321
-    #define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
-    #define CFG_DDR_CONTROL	0xc2000000	/* unbuffered,no DYN_PWR */
-    #define CFG_DDR_MODE	0x00000062	/* DLL,normal,seq,4/2.5 */
-    #define CFG_DDR_INTERVAL	0x05200100	/* autocharge,no open page */
-#endif
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8540 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8540ADS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
+
+/*
+ * These are used when DDR doesn't use SPD.
+ */
+#define CFG_SDRAM_SIZE	128		/* DDR is 128MB */
+#define CFG_DDR_CS0_BNDS	0x00000007	/* 0-128MB */
+#define CFG_DDR_CS0_CONFIG	0x80000002
+#define CFG_DDR_TIMING_1	0x37344321
+#define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
+#define CFG_DDR_CONTROL		0xc2000000	/* unbuffered,no DYN_PWR */
+#define CFG_DDR_MODE		0x00000062	/* DLL,normal,seq,4/2.5 */
+#define CFG_DDR_INTERVAL	0x05200100	/* autocharge,no open page */
 
 
 /*
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS to new DDR code.
  2008-08-20 23:22                   ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Kumar Gala
@ 2008-08-20 23:22                     ` Kumar Gala
  2008-08-20 23:22                       ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Kumar Gala
  2008-08-26 23:12                       ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Wolfgang Denk
  2008-08-26 23:12                     ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8560ads/Makefile     |   13 +-
 board/freescale/mpc8560ads/ddr.c        |  282 +++++++++++++++++++++++++++++++
 board/freescale/mpc8560ads/mpc8560ads.c |   15 ++-
 include/configs/MPC8560ADS.h            |   71 +++++---
 4 files changed, 348 insertions(+), 33 deletions(-)
 create mode 100644 board/freescale/mpc8560ads/ddr.c

diff --git a/board/freescale/mpc8560ads/Makefile b/board/freescale/mpc8560ads/Makefile
index 2d71cbc..67dbdeb 100644
--- a/board/freescale/mpc8560ads/Makefile
+++ b/board/freescale/mpc8560ads/Makefile
@@ -25,11 +25,14 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o law.o tlb.o
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
-SOBJS	:= $(addprefix $(obj),$(SOBJS))
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS-y))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
 	$(AR) $(ARFLAGS) $@ $(OBJS)
diff --git a/board/freescale/mpc8560ads/ddr.c b/board/freescale/mpc8560ads/ddr.c
new file mode 100644
index 0000000..ab59bf6
--- /dev/null
+++ b/board/freescale/mpc8560ads/ddr.c
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+
+static void
+get_spd(ddr1_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr1_spd_eeprom_t));
+}
+
+
+unsigned int
+fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+
+void
+fsl_ddr_get_spd(ddr1_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void
+fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int config_2 = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+		unsigned int *pconfig_2 = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			config_2 = ddr->cs0_config_2;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+			pconfig_2= (unsigned int *)&ddr->cs0_config_2;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			config_2 = ddr->cs1_config_2;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+			pconfig_2= (unsigned int *)&ddr->cs1_config_2;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			config_2 = ddr->cs2_config_2;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+			pconfig_2= (unsigned int *)&ddr->cs2_config_2;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			config_2 = ddr->cs3_config_2;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+			pconfig_2= (unsigned int *) &ddr->cs3_config_2;
+
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+		printf("cs%u_config_2       = %08X\t%p\n",
+		       i, config_2, pconfig_2);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+
+	printf("timing_cfg_4       = %08X\t%p\n",
+		ddr->timing_cfg_4, &ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\t%p\n",
+		ddr->timing_cfg_5, &ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\t%p\n",
+		ddr->ddr_zq_cntl, &ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\t%p\n",
+		ddr->ddr_wrlvl_cntl, &ddr->ddr_wrlvl_cntl);
+	printf("ddr_pd_cntl        = %08X\t%p\n",
+		ddr->ddr_pd_cntl, &ddr->ddr_pd_cntl);
+	printf("ddr_sr_cntr        = %08X\t%p\n",
+		ddr->ddr_sr_cntr, &ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_1, &ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_2, &ddr->ddr_sdram_rcw_2);
+
+	printf("debug_1            = %08X\t%p\n",
+	       ddr->debug_1, &ddr->debug_1);
+}
+
+void
+fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+			ddr->cs0_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+			ddr->cs1_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+			ddr->cs2_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+			ddr->cs3_config_2 = regs->cs[i].config_2;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/*
+	 * FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en
+	 */
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	asm("sync;isync;msync");
+	udelay(500);
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR1;
+}
+
+/*
+ * Technically, the memory controller on this part doesn't even
+ * have the clk_adjust field for lack of the SDRAM_CLK_CNTL register.
+ */
+
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 0;
+}
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 0;	/* Should be 0 for DDR1 */
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8560ads/mpc8560ads.c b/board/freescale/mpc8560ads/mpc8560ads.c
index 2c14a88..9b0c854 100644
--- a/board/freescale/mpc8560ads/mpc8560ads.c
+++ b/board/freescale/mpc8560ads/mpc8560ads.c
@@ -28,6 +28,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <ioports.h>
 #include <spd_sdram.h>
@@ -35,6 +36,8 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
+
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
 #endif
@@ -285,10 +288,16 @@ initdram(int board_type)
 	}
 #endif
 
-#if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram ();
+#ifdef CONFIG_SPD_EEPROM
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 #else
-	dram_size = fixed_sdram ();
+	dram_size = fixed_sdram();
 #endif
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
diff --git a/include/configs/MPC8560ADS.h b/include/configs/MPC8560ADS.h
index 3567d1c..98d829b 100644
--- a/include/configs/MPC8560ADS.h
+++ b/include/configs/MPC8560ADS.h
@@ -46,13 +46,6 @@
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #undef CONFIG_ETHER_ON_FCC             /* cpm FCC ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-#define CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 /*
@@ -100,28 +93,53 @@
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR1
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#undef CONFIG_FSL_DDR_INTERACTIVE
+
+#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#if defined(CONFIG_SPD_EEPROM)
-    /*
-     * Determine DDR configuration from I2C interface.
-     */
-    #define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
 
-#else
-    /*
-     * Manually set up DDR parameters
-     */
-    #define CFG_SDRAM_SIZE	128		/* DDR is 128MB */
-    #define CFG_DDR_CS0_BNDS	0x00000007	/* 0-128MB */
-    #define CFG_DDR_CS0_CONFIG	0x80000002
-    #define CFG_DDR_TIMING_1	0x37344321
-    #define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
-    #define CFG_DDR_CONTROL	0xc2000000	/* unbuffered,no DYN_PWR */
-    #define CFG_DDR_MODE	0x00000062	/* DLL,normal,seq,4/2.5 */
-    #define CFG_DDR_INTERVAL	0x05200100	/* autocharge,no open page */
-#endif
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8540 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8540ADS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
+
+/*
+ * These are used when DDR doesn't use SPD.
+ */
+#define CFG_SDRAM_SIZE	128		/* DDR is 128MB */
+#define CFG_DDR_CS0_BNDS	0x00000007	/* 0-128MB */
+#define CFG_DDR_CS0_CONFIG	0x80000002
+#define CFG_DDR_TIMING_1	0x37344321
+#define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
+#define CFG_DDR_CONTROL		0xc2000000	/* unbuffered,no DYN_PWR */
+#define CFG_DDR_MODE		0x00000062	/* DLL,normal,seq,4/2.5 */
+#define CFG_DDR_INTERVAL	0x05200100	/* autocharge,no open page */
 
 
 /*
@@ -293,6 +311,9 @@
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_VSPRINTF	1
+#define CFG_64BIT_STRTOUL	1
+
 /*
  * I2C
  */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS to new DDR code.
  2008-08-20 23:22                     ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Kumar Gala
@ 2008-08-20 23:22                       ` Kumar Gala
  2008-08-20 23:22                         ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Kumar Gala
  2008-08-26 23:12                         ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Wolfgang Denk
  2008-08-26 23:12                       ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8555cds/Makefile     |    1 +
 board/freescale/mpc8555cds/ddr.c        |  293 +++++++++++++++++++++++++++++++
 board/freescale/mpc8555cds/mpc8555cds.c |   12 ++-
 include/configs/MPC8555CDS.h            |   46 ++++-
 4 files changed, 341 insertions(+), 11 deletions(-)
 create mode 100644 board/freescale/mpc8555cds/ddr.c

diff --git a/board/freescale/mpc8555cds/Makefile b/board/freescale/mpc8555cds/Makefile
index 98f1530..c19a527 100644
--- a/board/freescale/mpc8555cds/Makefile
+++ b/board/freescale/mpc8555cds/Makefile
@@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(BOARD).a
 
 COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
diff --git a/board/freescale/mpc8555cds/ddr.c b/board/freescale/mpc8555cds/ddr.c
new file mode 100644
index 0000000..588bf9c
--- /dev/null
+++ b/board/freescale/mpc8555cds/ddr.c
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+static void
+get_spd(ddr1_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr1_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+void fsl_ddr_get_spd(ddr1_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void
+fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int config_2 = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+		unsigned int *pconfig_2 = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			config_2 = ddr->cs0_config_2;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+			pconfig_2= (unsigned int *)&ddr->cs0_config_2;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			config_2 = ddr->cs1_config_2;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+			pconfig_2= (unsigned int *)&ddr->cs1_config_2;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			config_2 = ddr->cs2_config_2;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+			pconfig_2= (unsigned int *)&ddr->cs2_config_2;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			config_2 = ddr->cs3_config_2;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+			pconfig_2= (unsigned int *) &ddr->cs3_config_2;
+
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+		printf("cs%u_config_2       = %08X\t%p\n",
+		       i, config_2, pconfig_2);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+
+	printf("timing_cfg_4       = %08X\t%p\n",
+		ddr->timing_cfg_4, &ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\t%p\n",
+		ddr->timing_cfg_5, &ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\t%p\n",
+		ddr->ddr_zq_cntl, &ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\t%p\n",
+		ddr->ddr_wrlvl_cntl, &ddr->ddr_wrlvl_cntl);
+	printf("ddr_pd_cntl        = %08X\t%p\n",
+		ddr->ddr_pd_cntl, &ddr->ddr_pd_cntl);
+	printf("ddr_sr_cntr        = %08X\t%p\n",
+		ddr->ddr_sr_cntr, &ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_1, &ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_2, &ddr->ddr_sdram_rcw_2);
+
+	printf("debug_1            = %08X\t%p\n",
+	       ddr->debug_1, &ddr->debug_1);
+}
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+			ddr->cs0_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+			ddr->cs1_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+			ddr->cs2_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+			ddr->cs3_config_2 = regs->cs[i].config_2;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en */
+	/* 8572 */
+	ddr->timing_cfg_4       = regs->timing_cfg_4;
+	ddr->timing_cfg_5       = regs->timing_cfg_5;
+	ddr->ddr_zq_cntl        = regs->ddr_zq_cntl;
+	ddr->ddr_wrlvl_cntl     = regs->ddr_wrlvl_cntl;
+	ddr->ddr_pd_cntl        = regs->ddr_pd_cntl;
+	ddr->ddr_sr_cntr        = regs->ddr_sr_cntr;
+	ddr->ddr_sdram_rcw_1    = regs->ddr_sdram_rcw_1;
+	ddr->ddr_sdram_rcw_2    = regs->ddr_sdram_rcw_2;
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	/*
+	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.
+	 */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR1;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 6;
+}
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 0;	/* Should be 0 for DDR1 */
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8555cds/mpc8555cds.c b/board/freescale/mpc8555cds/mpc8555cds.c
index 9a65101..25ac0aa 100644
--- a/board/freescale/mpc8555cds/mpc8555cds.c
+++ b/board/freescale/mpc8555cds/mpc8555cds.c
@@ -23,6 +23,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <ioports.h>
 #include <spd_sdram.h>
@@ -32,6 +33,7 @@
 #include "../common/cadmus.h"
 #include "../common/eeprom.h"
 #include "../common/via.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
@@ -261,7 +263,14 @@ initdram(int board_type)
 		udelay(200);
 	}
 #endif
-	dram_size = spd_sdram();
+
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/*
@@ -269,6 +278,7 @@ initdram(int board_type)
 	 */
 	ddr_enable_ecc(dram_size);
 #endif
+
 	/*
 	 * SDRAM Initialization
 	 */
diff --git a/include/configs/MPC8555CDS.h b/include/configs/MPC8555CDS.h
index 85c235c..4e393aa 100644
--- a/include/configs/MPC8555CDS.h
+++ b/include/configs/MPC8555CDS.h
@@ -40,13 +40,6 @@
 #define CONFIG_PCI
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-#undef CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 #define CONFIG_FSL_VIA
@@ -59,8 +52,6 @@
  */
 #define CONFIG_ASSUME_AMD_FLASH
 
-#define MPC85xx_DDR_SDRAM_CLK_CNTL	/* 85xx has clock control reg */
-
 #ifndef __ASSEMBLY__
 extern unsigned long get_clock_freq(void);
 #endif
@@ -85,13 +76,45 @@ extern unsigned long get_clock_freq(void);
 #define CFG_CCSRBAR_PHYS	CFG_CCSRBAR	/* physical addr of CCSRBAR */
 #define CFG_IMMR		CFG_CCSRBAR	/* PQII uses CFG_IMMR */
 
+
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR1
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#undef CONFIG_FSL_DDR_INTERACTIVE
+
+#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8540 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8540ADS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
 
 /*
  * Make sure required options are set
@@ -317,6 +340,9 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_VSPRINTF	1
+#define CFG_64BIT_STRTOUL	1
+
 /*
  * I2C
  */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS to new DDR code.
  2008-08-20 23:22                       ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Kumar Gala
@ 2008-08-20 23:22                         ` Kumar Gala
  2008-08-20 23:22                           ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Kumar Gala
  2008-08-26 23:13                           ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Wolfgang Denk
  2008-08-26 23:12                         ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8541cds/Makefile     |    1 +
 board/freescale/mpc8541cds/ddr.c        |  293 +++++++++++++++++++++++++++++++
 board/freescale/mpc8541cds/mpc8541cds.c |   10 +-
 include/configs/MPC8541CDS.h            |   44 ++++-
 4 files changed, 338 insertions(+), 10 deletions(-)
 create mode 100644 board/freescale/mpc8541cds/ddr.c

diff --git a/board/freescale/mpc8541cds/Makefile b/board/freescale/mpc8541cds/Makefile
index 98f1530..c19a527 100644
--- a/board/freescale/mpc8541cds/Makefile
+++ b/board/freescale/mpc8541cds/Makefile
@@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(BOARD).a
 
 COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
diff --git a/board/freescale/mpc8541cds/ddr.c b/board/freescale/mpc8541cds/ddr.c
new file mode 100644
index 0000000..588bf9c
--- /dev/null
+++ b/board/freescale/mpc8541cds/ddr.c
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+#define SDRAM_TYPE_LPDDR1  6
+#define SDRAM_TYPE_DDR3    7
+
+static void
+get_spd(ddr1_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr1_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+void fsl_ddr_get_spd(ddr1_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+	unsigned int i2c_address = 0;
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		if (ctrl_num == 0 && i == 0) {
+			i2c_address = SPD_EEPROM_ADDRESS1;
+		}
+		get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void
+fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	if (ctrl_num == 0)
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+	else
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int config_2 = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+		unsigned int *pconfig_2 = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			config_2 = ddr->cs0_config_2;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+			pconfig_2= (unsigned int *)&ddr->cs0_config_2;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			config_2 = ddr->cs1_config_2;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+			pconfig_2= (unsigned int *)&ddr->cs1_config_2;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			config_2 = ddr->cs2_config_2;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+			pconfig_2= (unsigned int *)&ddr->cs2_config_2;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			config_2 = ddr->cs3_config_2;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+			pconfig_2= (unsigned int *) &ddr->cs3_config_2;
+
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+		printf("cs%u_config_2       = %08X\t%p\n",
+		       i, config_2, pconfig_2);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+
+	printf("timing_cfg_4       = %08X\t%p\n",
+		ddr->timing_cfg_4, &ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\t%p\n",
+		ddr->timing_cfg_5, &ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\t%p\n",
+		ddr->ddr_zq_cntl, &ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\t%p\n",
+		ddr->ddr_wrlvl_cntl, &ddr->ddr_wrlvl_cntl);
+	printf("ddr_pd_cntl        = %08X\t%p\n",
+		ddr->ddr_pd_cntl, &ddr->ddr_pd_cntl);
+	printf("ddr_sr_cntr        = %08X\t%p\n",
+		ddr->ddr_sr_cntr, &ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_1, &ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\t%p\n",
+		ddr->ddr_sdram_rcw_2, &ddr->ddr_sdram_rcw_2);
+
+	printf("debug_1            = %08X\t%p\n",
+	       ddr->debug_1, &ddr->debug_1);
+}
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr;
+
+	switch (ctrl_num) {
+	case 0:
+		ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+		break;
+	case 1:
+		ddr = (void *)CFG_MPC85xx_DDR2_ADDR;
+		break;
+	default:
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+			ddr->cs0_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+			ddr->cs1_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+			ddr->cs2_config_2 = regs->cs[i].config_2;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+			ddr->cs3_config_2 = regs->cs[i].config_2;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en */
+	/* 8572 */
+	ddr->timing_cfg_4       = regs->timing_cfg_4;
+	ddr->timing_cfg_5       = regs->timing_cfg_5;
+	ddr->ddr_zq_cntl        = regs->ddr_zq_cntl;
+	ddr->ddr_wrlvl_cntl     = regs->ddr_wrlvl_cntl;
+	ddr->ddr_pd_cntl        = regs->ddr_pd_cntl;
+	ddr->ddr_sr_cntr        = regs->ddr_sr_cntr;
+	ddr->ddr_sdram_rcw_1    = regs->ddr_sdram_rcw_1;
+	ddr->ddr_sdram_rcw_2    = regs->ddr_sdram_rcw_2;
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	/*
+	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.
+	 */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR1;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 6;
+}
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 0;	/* Should be 0 for DDR1 */
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8541cds/mpc8541cds.c b/board/freescale/mpc8541cds/mpc8541cds.c
index 3669ba9..313111e 100644
--- a/board/freescale/mpc8541cds/mpc8541cds.c
+++ b/board/freescale/mpc8541cds/mpc8541cds.c
@@ -25,6 +25,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <ioports.h>
 #include <spd_sdram.h>
@@ -34,6 +35,7 @@
 #include "../common/cadmus.h"
 #include "../common/eeprom.h"
 #include "../common/via.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
@@ -263,7 +265,13 @@ initdram(int board_type)
 		udelay(200);
 	}
 #endif
-	dram_size = spd_sdram();
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/*
diff --git a/include/configs/MPC8541CDS.h b/include/configs/MPC8541CDS.h
index d948d76..7a21b78 100644
--- a/include/configs/MPC8541CDS.h
+++ b/include/configs/MPC8541CDS.h
@@ -40,12 +40,6 @@
 #define CONFIG_PCI
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-#undef CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
 
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
@@ -59,8 +53,6 @@
  */
 #define CONFIG_ASSUME_AMD_FLASH
 
-#define MPC85xx_DDR_SDRAM_CLK_CNTL	/* 85xx has clock control reg */
-
 #ifndef __ASSEMBLY__
 extern unsigned long get_clock_freq(void);
 #endif
@@ -88,10 +80,41 @@ extern unsigned long get_clock_freq(void);
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR1
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#undef CONFIG_FSL_DDR_INTERACTIVE
+
+#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8540 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8540ADS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+/*
+ * I2C addresses of SPD EEPROMs
+ */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
 
 /*
  * Make sure required options are set
@@ -317,6 +340,9 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_VSPRINTF	1
+#define CFG_64BIT_STRTOUL	1
+
 /*
  * I2C
  */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS to new DDR code.
  2008-08-20 23:22                         ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Kumar Gala
@ 2008-08-20 23:22                           ` Kumar Gala
  2008-08-20 23:22                             ` [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS " Kumar Gala
  2008-08-26 23:13                             ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Wolfgang Denk
  2008-08-26 23:13                           ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Wolfgang Denk
  1 sibling, 2 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8568mds/Makefile     |   14 +-
 board/freescale/mpc8568mds/ddr.c        |  248 +++++++++++++++++++++++++++++++
 board/freescale/mpc8568mds/mpc8568mds.c |   12 ++-
 include/configs/MPC8568MDS.h            |   49 +++++--
 4 files changed, 306 insertions(+), 17 deletions(-)
 create mode 100644 board/freescale/mpc8568mds/ddr.c

diff --git a/board/freescale/mpc8568mds/Makefile b/board/freescale/mpc8568mds/Makefile
index ecdc4d3..d499fb3 100644
--- a/board/freescale/mpc8568mds/Makefile
+++ b/board/freescale/mpc8568mds/Makefile
@@ -26,11 +26,15 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= $(BOARD).o bcsr.o law.o tlb.o
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
-SOBJS	:= $(addprefix $(obj),$(SOBJS))
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= bcsr.o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
+
+SRCS	:= $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS-y))
 
 $(LIB):	$(obj).depend $(OBJS) $(SOBJS)
 	$(AR) $(ARFLAGS) $@ $(OBJS)
diff --git a/board/freescale/mpc8568mds/ddr.c b/board/freescale/mpc8568mds/ddr.c
new file mode 100644
index 0000000..cd280be
--- /dev/null
+++ b/board/freescale/mpc8568mds/ddr.c
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+
+static void
+get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
+}
+
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
+		      unsigned int ctrl_num)
+{
+	unsigned int i;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		get_spd(&(ctrl_dimms_spd[i]), SPD_EEPROM_ADDRESS1);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_md_cntl  = %08X\t%p\n",
+		ddr->sdram_md_cntl, &ddr->sdram_md_cntl);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+}
+
+void
+fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+			      unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+		}
+	}
+
+	/*
+	 * Someone decided to use different names from the documentation...
+	 */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/*
+	 * FIXME: ECC?  Need to program err_disable, err_sbe, and err_int_en
+	 */
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	/*
+	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.
+	 */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR2;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 6;
+}
+
+/*
+ * factors to consider for CPO:
+ * 	- frequency
+ * 	- ddr1 vs. ddr2
+ *
+ * FIXME: figure out how to compute or tabulate good values for this
+ */
+
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 10;
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8568mds/mpc8568mds.c b/board/freescale/mpc8568mds/mpc8568mds.c
index 2ccff7d..9cc2b2d 100644
--- a/board/freescale/mpc8568mds/mpc8568mds.c
+++ b/board/freescale/mpc8568mds/mpc8568mds.c
@@ -25,6 +25,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <asm/immap_fsl_pci.h>
 #include <spd_sdram.h>
@@ -34,6 +35,7 @@
 #include <fdt_support.h>
 
 #include "bcsr.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 const qe_iop_conf_t qe_iop_conf_tab[] = {
 	/* GETH1 */
@@ -163,7 +165,14 @@ initdram(int board_type)
 		udelay(200);
 	}
 #endif
-	dram_size = spd_sdram();
+
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/*
@@ -171,6 +180,7 @@ initdram(int board_type)
 	 */
 	ddr_enable_ecc(dram_size);
 #endif
+
 	/*
 	 * SDRAM Initialization
 	 */
diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h
index a82d528..53dfb50 100644
--- a/include/configs/MPC8568MDS.h
+++ b/include/configs/MPC8568MDS.h
@@ -41,14 +41,6 @@
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_QE			/* Enable QE */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-/*#define CONFIG_DDR_2T_TIMING		 Sets the 2T timing bit */
-
-/*#define CONFIG_DDR_ECC*/			/* only for ECC DDR module */
-/*#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER*/	/* DDR controller or DMA? */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
-
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 /*
@@ -58,8 +50,6 @@
  */
 #define CONFIG_ASSUME_AMD_FLASH
 
-#define MPC85xx_DDR_SDRAM_CLK_CNTL	/* 85xx has clock control reg */
-
 #ifndef __ASSEMBLY__
 extern unsigned long get_clock_freq(void);
 #endif						  /*Replace a call to get_clock_freq (after it is implemented)*/
@@ -98,10 +88,44 @@ extern unsigned long get_clock_freq(void);
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR2
+#undef CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#define CONFIG_DDR_DLL			/* possible DLL fix needed */
+#undef CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
+
+#define CONFIG_MEM_INIT_VALUE	0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8568 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8568DS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+ /*
+  * I2C addresses of SPD EEPROMs
+  */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
 
 /*
  * Make sure required options are set
@@ -302,6 +326,9 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_VSPRINTF	1
+#define CFG_64BIT_STRTOUL	1
+
 /*
  * I2C
  */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS to new DDR code.
  2008-08-20 23:22                           ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Kumar Gala
@ 2008-08-20 23:22                             ` Kumar Gala
  2008-08-26 23:13                               ` Wolfgang Denk
  2008-08-26 23:13                             ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Wolfgang Denk
  1 sibling, 1 reply; 34+ messages in thread
From: Kumar Gala @ 2008-08-20 23:22 UTC (permalink / raw)
  To: u-boot

From: Jon Loeliger <jdl@freescale.com>

Signed-off-by: Jon Loeliger <jdl@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 board/freescale/mpc8548cds/Makefile     |    1 +
 board/freescale/mpc8548cds/ddr.c        |  239 +++++++++++++++++++++++++++++++
 board/freescale/mpc8548cds/mpc8548cds.c |   12 ++-
 include/configs/MPC8548CDS.h            |   49 +++++--
 4 files changed, 289 insertions(+), 12 deletions(-)
 create mode 100644 board/freescale/mpc8548cds/ddr.c

diff --git a/board/freescale/mpc8548cds/Makefile b/board/freescale/mpc8548cds/Makefile
index 98f1530..c19a527 100644
--- a/board/freescale/mpc8548cds/Makefile
+++ b/board/freescale/mpc8548cds/Makefile
@@ -27,6 +27,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)lib$(BOARD).a
 
 COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
diff --git a/board/freescale/mpc8548cds/ddr.c b/board/freescale/mpc8548cds/ddr.c
new file mode 100644
index 0000000..1856ebc
--- /dev/null
+++ b/board/freescale/mpc8548cds/ddr.c
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <../cpu/mpc8xxx/fsl_ddr_sdram.h>
+
+#define SDRAM_TYPE_DDR1    2
+#define SDRAM_TYPE_DDR2    3
+
+static void
+get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
+{
+	i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
+}
+
+unsigned int fsl_ddr_get_mem_data_rate(void)
+{
+	return get_ddr_freq(0);
+}
+
+void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
+			unsigned int ctrl_num)
+{
+	unsigned int i;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+		get_spd(&(ctrl_dimms_spd[i]), SPD_EEPROM_ADDRESS1);
+	}
+}
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_dump_memctl_regs(unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		unsigned int bnds = 0;
+		unsigned int config = 0;
+		unsigned int *pbnds = NULL;
+		unsigned int *pconfig = NULL;
+
+		if (i == 0) {
+			bnds     = ddr->cs0_bnds;
+			config   = ddr->cs0_config;
+			pbnds    = (unsigned int *)&ddr->cs0_bnds;
+			pconfig  = (unsigned int *)&ddr->cs0_config;
+
+		} else if (i == 1) {
+			bnds     = ddr->cs1_bnds;
+			config   = ddr->cs1_config;
+			pbnds    = (unsigned int *)&ddr->cs1_bnds;
+			pconfig  = (unsigned int *)&ddr->cs1_config;
+
+		} else if (i == 2) {
+			bnds     = ddr->cs2_bnds;
+			config   = ddr->cs2_config;
+			pbnds    = (unsigned int *)&ddr->cs2_bnds;
+			pconfig  = (unsigned int *)&ddr->cs2_config;
+
+		} else {
+			bnds     = ddr->cs3_bnds;
+			config   = ddr->cs3_config;
+			pbnds    = (unsigned int *) &ddr->cs3_bnds;
+			pconfig  = (unsigned int *) &ddr->cs3_config;
+		}
+
+		printf("cs%u_bnds           = %08X\t%p\n", i, bnds, pbnds);
+		printf("cs%u_config         = %08X\t%p\n", i, config, pconfig);
+	}
+
+	/*
+	 * Due to inconsistencies between immap_85xx.h and immap_86xx.h,
+	 * you will have to modify the structure member names by hand
+	 * between architectures.
+	 */
+	printf("timing_cfg_3       = %08X\t%p\n",
+	       ddr->timing_cfg_3, &ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\t%p\n",
+	       ddr->timing_cfg_0, &ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\t%p\n",
+	       ddr->timing_cfg_1, &ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\t%p\n",
+	       ddr->timing_cfg_2, &ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\t%p\n",
+	       ddr->sdram_cfg, &ddr->sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\t%p\n",
+	       ddr->sdram_cfg_2, &ddr->sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\t%p\n",
+		ddr->sdram_mode, &ddr->sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\t%p\n",
+		ddr->sdram_mode_2, &ddr->sdram_mode_2);
+	printf("ddr_sdram_md_cntl  = %08X\t%p\n",
+		ddr->sdram_md_cntl, &ddr->sdram_md_cntl);
+	printf("ddr_sdram_interval = %08X\t%p\n",
+		ddr->sdram_interval, &ddr->sdram_interval);
+	printf("ddr_data_init      = %08X\t%p\n",
+		ddr->sdram_data_init, &ddr->sdram_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\t%p\n",
+		ddr->sdram_clk_cntl, &ddr->sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\t%p\n",
+		ddr->init_addr, &ddr->init_addr);
+	printf("ddr_init_ext_addr  = %08X\t%p\n",
+		ddr->init_ext_addr, &ddr->init_ext_addr);
+}
+
+
+void fsl_ddr_set_memctl_regs(const fsl_memctl_config_regs_t *regs,
+				unsigned int ctrl_num)
+{
+	unsigned int i;
+	volatile ccsr_ddr_t *ddr = (void *)CFG_MPC85xx_DDR_ADDR;
+
+	if (ctrl_num) {
+		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+		return;
+	}
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (i == 0) {
+			ddr->cs0_bnds = regs->cs[i].bnds;
+			ddr->cs0_config = regs->cs[i].config;
+
+		} else if (i == 1) {
+			ddr->cs1_bnds = regs->cs[i].bnds;
+			ddr->cs1_config = regs->cs[i].config;
+
+		} else if (i == 2) {
+			ddr->cs2_bnds = regs->cs[i].bnds;
+			ddr->cs2_config = regs->cs[i].config;
+
+		} else if (i == 3) {
+			ddr->cs3_bnds = regs->cs[i].bnds;
+			ddr->cs3_config = regs->cs[i].config;
+		}
+	}
+
+	/* Someone decided to use different names from the documentation... */
+	ddr->timing_cfg_3       = regs->timing_cfg_3;
+	ddr->timing_cfg_0       = regs->timing_cfg_0;
+	ddr->timing_cfg_1       = regs->timing_cfg_1;
+	ddr->timing_cfg_2       = regs->timing_cfg_2;
+	ddr->sdram_cfg_2        = regs->ddr_sdram_cfg_2;
+	ddr->sdram_mode         = regs->ddr_sdram_mode;
+	ddr->sdram_mode_2       = regs->ddr_sdram_mode_2;
+	ddr->sdram_interval     = regs->ddr_sdram_interval;
+	ddr->sdram_data_init    = regs->ddr_data_init;
+	ddr->sdram_clk_cntl     = regs->ddr_sdram_clk_cntl;
+	ddr->init_addr          = regs->ddr_init_addr;
+	ddr->init_ext_addr      = regs->ddr_init_ext_addr;
+
+	/* FIXME: ECC? Need to program err_disable, err_sbe, and err_int_en */
+
+	/*
+	 * 200 painful micro-seconds must elapse between
+	 * the DDR clock setup and the DDR config enable.
+	 */
+	udelay(200);
+	asm volatile("sync;isync");
+
+	ddr->sdram_cfg = regs->ddr_sdram_cfg;
+
+	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+	while (ddr->sdram_cfg_2 & 0x10) {
+		udelay(10000);		/* throttle polling rate */
+	}
+}
+
+unsigned int fsl_ddr_type_function(void)
+{
+	return SDRAM_TYPE_DDR2;
+}
+
+/*
+ * factors to consider for clock adjust:
+ * 	- number of chips on bus
+ * 	- position of slot
+ * 	- DDR1 vs. DDR2?
+ * 	- ???
+ *
+ * FIXME: need to figure out the function parameters necessary to compute
+ * FIXME: a clock adjust value
+ */
+unsigned int fsl_ddr_clk_adjust_function(void)
+{
+	return 7;
+}
+
+/*
+ * factors to consider for CPO:
+ * 	- frequency
+ * 	- ddr1 vs. ddr2
+ *
+ * FIXME: figure out how to compute or tabulate good values for this
+ */
+unsigned int fsl_ddr_cpo_override_function(void)
+{
+	return 10;
+}
+
+/*
+ * factors to consider for write data delay:
+ * 	- number of DIMMs
+ *
+ * 1 = 1/4 clock delay
+ * 2 = 1/2 clock delay
+ * 3 = 3/4 clock delay
+ * 4 = 1   clock delay
+ * 5 = 5/4 clock delay
+ * 6 = 3/2 clock delay
+ */
+unsigned int fsl_ddr_write_data_delay_function(void)
+{
+	return 3;
+}
+
+/*
+ * factors to consider for half-strength driver enable:
+ * 	- number of DIMMs installed
+ */
+unsigned int fsl_ddr_half_strength_driver_enable_function(void)
+{
+	return 0;
+}
diff --git a/board/freescale/mpc8548cds/mpc8548cds.c b/board/freescale/mpc8548cds/mpc8548cds.c
index 0b037cc..98752b8 100644
--- a/board/freescale/mpc8548cds/mpc8548cds.c
+++ b/board/freescale/mpc8548cds/mpc8548cds.c
@@ -25,6 +25,7 @@
 #include <common.h>
 #include <pci.h>
 #include <asm/processor.h>
+#include <asm/mmu.h>
 #include <asm/immap_85xx.h>
 #include <asm/immap_fsl_pci.h>
 #include <spd_sdram.h>
@@ -35,6 +36,7 @@
 #include "../common/cadmus.h"
 #include "../common/eeprom.h"
 #include "../common/via.h"
+#include "../cpu/mpc8xxx/fsl_ddr_sdram.h"
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 extern void ddr_enable_ecc(unsigned int dram_size);
@@ -111,7 +113,14 @@ initdram(int board_type)
 		udelay(200);
 	}
 #endif
-	dram_size = spd_sdram();
+
+	dram_size = fsl_ddr_sdram();
+	printf("dram_size = %u\n", dram_size);
+
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	printf("dram_size = %u after setup_ddr_tlbs\n", dram_size);
+
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/*
@@ -119,6 +128,7 @@ initdram(int board_type)
 	 */
 	ddr_enable_ecc(dram_size);
 #endif
+
 	/*
 	 * SDRAM Initialization
 	 */
diff --git a/include/configs/MPC8548CDS.h b/include/configs/MPC8548CDS.h
index 33c5c93..ce1b00b 100644
--- a/include/configs/MPC8548CDS.h
+++ b/include/configs/MPC8548CDS.h
@@ -46,15 +46,7 @@
 
 #define CONFIG_TSEC_ENET		/* tsec ethernet support */
 #define CONFIG_ENV_OVERWRITE
-#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
-#define CONFIG_DDR_DLL			/* possible DLL fix needed */
-#undef CONFIG_DDR_2T_TIMING		/* Sets the 2T timing bit */
-
-#define CONFIG_DDR_ECC			/* only for ECC DDR module */
-#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
-#define CONFIG_MEM_INIT_VALUE		0xDeadBeef
 #define CONFIG_INTERRUPTS		/* enable pci, srio, ddr interrupts */
-
 #define CONFIG_FSL_LAW		1	/* Use common FSL init code */
 
 #define CONFIG_FSL_VIA
@@ -67,8 +59,6 @@
  */
 #define CONFIG_ASSUME_AMD_FLASH
 
-#define MPC85xx_DDR_SDRAM_CLK_CNTL	/* 85xx has clock control reg */
-
 #ifndef __ASSEMBLY__
 extern unsigned long get_clock_freq(void);
 #endif
@@ -106,10 +96,44 @@ extern unsigned long get_clock_freq(void);
 /*
  * DDR Setup
  */
+#define CONFIG_FSL_DDR2
+#undef CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SPD_EEPROM		/* Use SPD EEPROM for DDR setup*/
+#define CONFIG_DDR_SPD
+#define CONFIG_DDR_DLL			/* possible DLL fix needed */
+
+#undef CONFIG_ECC_INIT_VIA_DDRCONTROLLER	/* DDR controller or DMA? */
+#define CONFIG_MEM_INIT_VALUE	0xDeadBeef
+
 #define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
 
-#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+
+/*
+ * Number of memory controllers on device
+ */
+#define CONFIG_NUM_DDR_CONTROLLERS	1
+
+/*
+ * Number of DIMM slots per memory controller
+ */
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+
+/*
+ * Number of chip selects per memory controller
+ *
+ * The MPC8568 (the chip) has 4 chip selects per memory controller.
+ * However, the MPC8568DS (the board) has only 1 DIMM slot per memory
+ * controller, so therefore it only has 2 chip selects per memory
+ * controller that are actually connected.
+ */
+#define CONFIG_CHIP_SELECTS_PER_CTRL	(2 * CONFIG_DIMM_SLOTS_PER_CTLR)
+
+ /*
+  * I2C addresses of SPD EEPROMs
+  */
+#define SPD_EEPROM_ADDRESS1	0x51	/* CTLR 0 DIMM 0 */
+
 
 /*
  * Make sure required options are set
@@ -342,6 +366,9 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_OF_BOARD_SETUP		1
 #define CONFIG_OF_STDOUT_VIA_ALIAS	1
 
+#define CFG_64BIT_VSPRINTF	1
+#define CFG_64BIT_STRTOUL	1
+
 /*
  * I2C
  */
-- 
1.5.5.1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3
  2008-08-20 23:22 [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Kumar Gala
  2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
@ 2008-08-26 23:07 ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:07 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-1-git-send-email-galak@kernel.crashing.org> you wrote:
> From: James Yang <James.Yang@freescale.com>
> 
> Also added a few helper functions for DDR1 & DDR2 to print SPD info and
> verify the checksum.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  common/Makefile   |    1 +
>  common/ddr_spd.c  |  519 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/ddr_spd.h |  292 ++++++++++++++++++++++++++++++
>  3 files changed, 812 insertions(+), 0 deletions(-)
>  create mode 100644 common/ddr_spd.c
>  create mode 100644 include/ddr_spd.h

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Blast medicine anyway!  We've learned to tie into every organ in the
human body but one.  The brain!  The brain is what life is all about.
	-- McCoy, "The Menagerie", stardate 3012.4

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code.
  2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
  2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
@ 2008-08-26 23:08   ` Wolfgang Denk
  2008-08-29 22:16   ` Peter Tyser
  2 siblings, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:08 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-2-git-send-email-galak@kernel.crashing.org> you wrote:
> Signed-off-by: James Yang <James.Yang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
> Signed-off-by: Ed Swarthout <Ed.Swarthout@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  cpu/mpc85xx/Makefile               |    9 +
>  cpu/mpc86xx/Makefile               |    4 +
>  cpu/mpc8xxx/Makefile               |   29 +
>  cpu/mpc8xxx/common_timing_params.h |   55 ++
>  cpu/mpc8xxx/ddr2_dimm_params.h     |   86 +++
>  cpu/mpc8xxx/fsl_ddr_ctrl.c         | 1002 +++++++++++++++++++++++++++++++
>  cpu/mpc8xxx/fsl_ddr_sdram.c        | 1134 ++++++++++++++++++++++++++++++++++++
>  cpu/mpc8xxx/fsl_ddr_sdram.h        |   90 +++
>  cpu/mpc8xxx/fsl_memctrl.h          |   44 ++
>  cpu/mpc8xxx/fsl_util.c             |   59 ++
>  cpu/mpc8xxx/memctl_options.h       |   85 +++
>  11 files changed, 2597 insertions(+), 0 deletions(-)
>  create mode 100644 cpu/mpc8xxx/Makefile
>  create mode 100644 cpu/mpc8xxx/common_timing_params.h
>  create mode 100644 cpu/mpc8xxx/ddr2_dimm_params.h
>  create mode 100644 cpu/mpc8xxx/fsl_ddr_ctrl.c
>  create mode 100644 cpu/mpc8xxx/fsl_ddr_sdram.c
>  create mode 100644 cpu/mpc8xxx/fsl_ddr_sdram.h
>  create mode 100644 cpu/mpc8xxx/fsl_memctrl.h
>  create mode 100644 cpu/mpc8xxx/fsl_util.c
>  create mode 100644 cpu/mpc8xxx/memctl_options.h

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I had the rare misfortune of being one of the first people to try and
implement a PL/1 compiler.                             -- T. Cheatham

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support
  2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
  2008-08-20 23:22     ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Kumar Gala
@ 2008-08-26 23:08     ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:08 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-3-git-send-email-galak@kernel.crashing.org> you wrote:
> Signed-off-by: James Yang <James.Yang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  cpu/mpc8xxx/fsl_ddr1.c |  342 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 342 insertions(+), 0 deletions(-)
>  create mode 100644 cpu/mpc8xxx/fsl_ddr1.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Any sufficiently advanced technology is indistinguishable from magic.
                                                   - Arthur C. Clarke

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support
  2008-08-20 23:22     ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Kumar Gala
  2008-08-20 23:22       ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Kumar Gala
@ 2008-08-26 23:08       ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:08 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-4-git-send-email-galak@kernel.crashing.org> you wrote:
> Signed-off-by: James Yang <James.Yang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  cpu/mpc8xxx/fsl_ddr2.c |  339 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 339 insertions(+), 0 deletions(-)
>  create mode 100644 cpu/mpc8xxx/fsl_ddr2.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
All a hacker needs is a tight PUSHJ, a loose pair of UUOs, and a warm
place to shift.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support
  2008-08-20 23:22       ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Kumar Gala
  2008-08-20 23:22         ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Kumar Gala
@ 2008-08-26 23:09         ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:09 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-5-git-send-email-galak@kernel.crashing.org> you wrote:
> Provide a mechanism to allow interactive configuration of DDR params.  This
> is useful when trying to test various DDR settings to determine optimal
> configuration values for a given board.
> 
> Signed-off-by: James Yang <James.Yang@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  cpu/mpc8xxx/Makefile              |    2 +
>  cpu/mpc8xxx/fsl_ddr_interactive.c | 1238 +++++++++++++++++++++++++++++++++++++
>  cpu/mpc8xxx/fsl_ddr_sdram.c       |   12 +-
>  cpu/mpc8xxx/fsl_ddr_sdram.h       |    3 +
>  4 files changed, 1254 insertions(+), 1 deletions(-)
>  create mode 100644 cpu/mpc8xxx/fsl_ddr_interactive.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Those who do not  understand  Unix  are  condemned  to  reinvent  it,
poorly.              - Henry Spencer, University of Toronto Unix hack

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar()
  2008-08-20 23:22         ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Kumar Gala
  2008-08-20 23:22           ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code Kumar Gala
@ 2008-08-26 23:10           ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:10 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-6-git-send-email-galak@kernel.crashing.org> you wrote:
> Make fsl_ddr_sdram_set_lawbar() a weak function to allow board code to
> override if desired.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  drivers/misc/fsl_law.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 88 insertions(+), 0 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Research is what I'm doing when I don't know what I'm doing.
                                                 -- Wernher von Braun

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code
  2008-08-20 23:22           ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code Kumar Gala
  2008-08-20 23:22             ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new " Kumar Gala
@ 2008-08-26 23:10             ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:10 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-7-git-send-email-galak@kernel.crashing.org> you wrote:
> Provide a helper function that board code can call to map TLBs when
> setting up DDR.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  cpu/mpc85xx/tlb.c     |   64 +++++++++++++++++++++++++++++++++++++++++++++++++
>  include/asm-ppc/mmu.h |    1 +
>  2 files changed, 65 insertions(+), 0 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"We don't have to protect the environment -- the Second Coming is  at
hand."                                                   - James Watt

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new DDR code.
  2008-08-20 23:22             ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new " Kumar Gala
  2008-08-20 23:22               ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Kumar Gala
@ 2008-08-26 23:11               ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:11 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-8-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  Makefile                                  |    3 +
>  board/freescale/mpc8641hpcn/Makefile      |    8 +-
>  board/freescale/mpc8641hpcn/ddr.c         |  234 +++++++++++++++++++++++++++++
>  board/freescale/mpc8641hpcn/mpc8641hpcn.c |    5 +-
>  cpu/mpc86xx/Makefile                      |    1 -
>  include/configs/MPC8641HPCN.h             |  117 ++++++++-------
>  6 files changed, 307 insertions(+), 61 deletions(-)
>  create mode 100644 board/freescale/mpc8641hpcn/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Memories of you remind me of you.                   - Karl Lehenbauer

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD to new DDR code.
  2008-08-20 23:22               ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Kumar Gala
  2008-08-20 23:22                 ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Kumar Gala
@ 2008-08-26 23:11                 ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:11 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-9-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8610hpcd/Makefile      |   10 +-
>  board/freescale/mpc8610hpcd/ddr.c         |  223 +++++++++++++++++++++++++++++
>  board/freescale/mpc8610hpcd/mpc8610hpcd.c |    3 +-
>  include/configs/MPC8610HPCD.h             |   50 +++++--
>  4 files changed, 264 insertions(+), 22 deletions(-)
>  create mode 100644 board/freescale/mpc8610hpcd/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Am besten betrachten Sie Fehlermeldungen als eine  Art  Psycho-Test,
mit  dem  herausgefunden  werden soll, wie belastbar Sie sind."
 - Dr. R. Wonneberger, Kompaktf?hrer LaTeX, Kap. 1.6: Fehlermeldungen

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS to new DDR code.
  2008-08-20 23:22                 ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Kumar Gala
  2008-08-20 23:22                   ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Kumar Gala
@ 2008-08-26 23:11                   ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:11 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-10-git-send-email-galak@kernel.crashing.org> you wrote:
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  Makefile                              |    1 +
>  board/freescale/mpc8544ds/Makefile    |    9 +-
>  board/freescale/mpc8544ds/ddr.c       |  242 +++++++++++++++++++++++++++++++++
>  board/freescale/mpc8544ds/mpc8544ds.c |   11 +-
>  cpu/mpc85xx/Makefile                  |    2 +-
>  include/configs/MPC8544DS.h           |   52 ++++++--
>  6 files changed, 298 insertions(+), 19 deletions(-)
>  create mode 100644 board/freescale/mpc8544ds/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
There is is no reason for any individual to have a computer in  their
home.      -- Ken Olsen (President of Digital Equipment Corporation),
              Convention of the World Future Society, in Boston, 1977

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS to new DDR code.
  2008-08-20 23:22                   ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Kumar Gala
  2008-08-20 23:22                     ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Kumar Gala
@ 2008-08-26 23:12                     ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:12 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-11-git-send-email-galak@kernel.crashing.org> you wrote:
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8540ads/Makefile     |   13 +-
>  board/freescale/mpc8540ads/ddr.c        |  282 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8540ads/mpc8540ads.c |   16 ++-
>  include/configs/MPC8540ADS.h            |   70 +++++---
>  4 files changed, 346 insertions(+), 35 deletions(-)
>  create mode 100644 board/freescale/mpc8540ads/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"...and the fully armed nuclear warheads, are, of  course,  merely  a
courtesy detail."

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS to new DDR code.
  2008-08-20 23:22                     ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Kumar Gala
  2008-08-20 23:22                       ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Kumar Gala
@ 2008-08-26 23:12                       ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:12 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-12-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8560ads/Makefile     |   13 +-
>  board/freescale/mpc8560ads/ddr.c        |  282 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8560ads/mpc8560ads.c |   15 ++-
>  include/configs/MPC8560ADS.h            |   71 +++++---
>  4 files changed, 348 insertions(+), 33 deletions(-)
>  create mode 100644 board/freescale/mpc8560ads/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The connection between the language in which we think/program and the
problems and solutions we can imagine is very close. For this  reason
restricting  language  features  with  the intent of eliminating pro-
grammer errors is at best dangerous.
               - Bjarne Stroustrup in "The  C++ Programming Language"

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS to new DDR code.
  2008-08-20 23:22                       ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Kumar Gala
  2008-08-20 23:22                         ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Kumar Gala
@ 2008-08-26 23:12                         ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:12 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-13-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8555cds/Makefile     |    1 +
>  board/freescale/mpc8555cds/ddr.c        |  293 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8555cds/mpc8555cds.c |   12 ++-
>  include/configs/MPC8555CDS.h            |   46 ++++-
>  4 files changed, 341 insertions(+), 11 deletions(-)
>  create mode 100644 board/freescale/mpc8555cds/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
All I ask is a chance to prove that money can't make me happy.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS to new DDR code.
  2008-08-20 23:22                         ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Kumar Gala
  2008-08-20 23:22                           ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Kumar Gala
@ 2008-08-26 23:13                           ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:13 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-14-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8541cds/Makefile     |    1 +
>  board/freescale/mpc8541cds/ddr.c        |  293 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8541cds/mpc8541cds.c |   10 +-
>  include/configs/MPC8541CDS.h            |   44 ++++-
>  4 files changed, 338 insertions(+), 10 deletions(-)
>  create mode 100644 board/freescale/mpc8541cds/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Ada is PL/I trying to be Smalltalk.                 - Codoso diBlini

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS to new DDR code.
  2008-08-20 23:22                           ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Kumar Gala
  2008-08-20 23:22                             ` [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS " Kumar Gala
@ 2008-08-26 23:13                             ` Wolfgang Denk
  1 sibling, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:13 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-15-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8568mds/Makefile     |   14 +-
>  board/freescale/mpc8568mds/ddr.c        |  248 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8568mds/mpc8568mds.c |   12 ++-
>  include/configs/MPC8568MDS.h            |   49 +++++--
>  4 files changed, 306 insertions(+), 17 deletions(-)
>  create mode 100644 board/freescale/mpc8568mds/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The complexity of software is an essential property, not an  acciden-
tal  one. Hence, descriptions of a software entity that abstract away
its complexity often abstract away its essence.    - Fred Brooks, Jr.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS to new DDR code.
  2008-08-20 23:22                             ` [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS " Kumar Gala
@ 2008-08-26 23:13                               ` Wolfgang Denk
  0 siblings, 0 replies; 34+ messages in thread
From: Wolfgang Denk @ 2008-08-26 23:13 UTC (permalink / raw)
  To: u-boot

Dear Kumar Gala,

In message <1219274578-30322-16-git-send-email-galak@kernel.crashing.org> you wrote:
> From: Jon Loeliger <jdl@freescale.com>
> 
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
>  board/freescale/mpc8548cds/Makefile     |    1 +
>  board/freescale/mpc8548cds/ddr.c        |  239 +++++++++++++++++++++++++++++++
>  board/freescale/mpc8548cds/mpc8548cds.c |   12 ++-
>  include/configs/MPC8548CDS.h            |   49 +++++--
>  4 files changed, 289 insertions(+), 12 deletions(-)
>  create mode 100644 board/freescale/mpc8548cds/ddr.c

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"In the face of entropy and nothingness, you kind of have to  pretend
it's  not  there  if  you  want  to  keep writing good code."
- Karl Lehenbauer

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code.
  2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
  2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
  2008-08-26 23:08   ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Wolfgang Denk
@ 2008-08-29 22:16   ` Peter Tyser
  2008-08-29 23:51     ` Kumar Gala
  2 siblings, 1 reply; 34+ messages in thread
From: Peter Tyser @ 2008-08-29 22:16 UTC (permalink / raw)
  To: u-boot

Hello,

[snip]

> +
> +/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
> +static void set_ddr_sdram_cfg_2(fsl_memctl_config_regs_t *ddr,
> +			       const memctl_options_t *popts)
> +{
> +	unsigned int frc_sr = 0;	/* Force self refresh */
> +	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
> +	unsigned int dll_rst_dis;	/* DLL reset disable */
> +	unsigned int dqs_cfg;		/* DQS configuration */
> +	unsigned int odt_cfg;		/* ODT configuration */
> +	unsigned int num_pr;		/* Number of posted refreshes */
> +	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
> +	unsigned int ap_en;		/* Address Parity Enable */
> +	unsigned int d_init;		/* DRAM data initialization */
> +	unsigned int rcw_en = 0;	/* Register Control Word Enable */
> +	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
> +
> +	dll_rst_dis = 1;	/* Make this configurable */
> +	dqs_cfg = popts->DQS_config;
> +	if (popts->cs_local_opts[0].odt_rd_cfg
> +	    || popts->cs_local_opts[0].odt_wr_cfg) {
> +		/* FIXME */
> +		odt_cfg = 2;
> +	} else {
> +		odt_cfg = 0;
> +	}
> +
> +	num_pr = 1;	/* Make this configurable */
> +
> +	/*
> +	 * 8572 manual says
> +	 *     {TIMING_CFG_1[PRETOACT]
> +	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
> +	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
> +	 *      << DDR_SDRAM_INTERVAL[REFINT]
> +	 */
> +
> +	obc_cfg = 0;	/* Make this configurable? */
> +	ap_en = 0;	/* Make this configurable? */
> +
> +#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
> +	/* Use the DDR controller to auto initialize memory. */
> +	d_init = 1;
> +	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
> +	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
> +#else
> +	/* Memory will be initialized via DMA, or not at all. */
> +	d_init = 0;
> +#endif
> +

I'm using the current head (33aa4eac66b71c797bbc13b3afe432a2132947d4) on
a mpc8572-based board.  It uses DDR2 and has support for ECC.  While
enabling ECC support, I noticed that the "old"
CONFIG_ECC_INIT_VIA_DDRCONTROLLER define is still being used to enable
memory initialization on bootup  while a new ECC_init_using_memctl field
in the memctl_options_s structure is also present.

Currently it looks like ECC_init_using_memctl doesn't do anything and is
only referenced in one location below:

> +	/* Pick ECC modes */
> +#ifdef CONFIG_DDR_ECC
> +	popts->ECC_mode = 1;		  /* 0 = disabled, 1 = enabled */
> +#else
> +	popts->ECC_mode = 0;		  /* 0 = disabled, 1 = enabled */
> +#endif
> +	popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */

The intended functionality of CONFIG_ECC_INIT_VIA_DDRCONTROLLER and
ECC_init_using_memctl seem to be the same, but only one of them is being
used, and they currently are unrelated which is a bit confusing.

Should the ECC_init_using_memctl field be removed, or is the intention
to replace CONFIG_ECC_INIT_VIA_DDRCONTROLLER functionality with
ECC_init_using_memctl as some point?

Thanks for any insight,
Peter

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code.
  2008-08-29 22:16   ` Peter Tyser
@ 2008-08-29 23:51     ` Kumar Gala
  0 siblings, 0 replies; 34+ messages in thread
From: Kumar Gala @ 2008-08-29 23:51 UTC (permalink / raw)
  To: u-boot


On Aug 29, 2008, at 5:16 PM, Peter Tyser wrote:

> Hello,
>
> [snip]
>
>> +
>> +/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
>> +static void set_ddr_sdram_cfg_2(fsl_memctl_config_regs_t *ddr,
>> +			       const memctl_options_t *popts)
>> +{
>> +	unsigned int frc_sr = 0;	/* Force self refresh */
>> +	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
>> +	unsigned int dll_rst_dis;	/* DLL reset disable */
>> +	unsigned int dqs_cfg;		/* DQS configuration */
>> +	unsigned int odt_cfg;		/* ODT configuration */
>> +	unsigned int num_pr;		/* Number of posted refreshes */
>> +	unsigned int obc_cfg;		/* On-The-Fly Burst Chop Cfg */
>> +	unsigned int ap_en;		/* Address Parity Enable */
>> +	unsigned int d_init;		/* DRAM data initialization */
>> +	unsigned int rcw_en = 0;	/* Register Control Word Enable */
>> +	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
>> +
>> +	dll_rst_dis = 1;	/* Make this configurable */
>> +	dqs_cfg = popts->DQS_config;
>> +	if (popts->cs_local_opts[0].odt_rd_cfg
>> +	    || popts->cs_local_opts[0].odt_wr_cfg) {
>> +		/* FIXME */
>> +		odt_cfg = 2;
>> +	} else {
>> +		odt_cfg = 0;
>> +	}
>> +
>> +	num_pr = 1;	/* Make this configurable */
>> +
>> +	/*
>> +	 * 8572 manual says
>> +	 *     {TIMING_CFG_1[PRETOACT]
>> +	 *      + [DDR_SDRAM_CFG_2[NUM_PR]
>> +	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
>> +	 *      << DDR_SDRAM_INTERVAL[REFINT]
>> +	 */
>> +
>> +	obc_cfg = 0;	/* Make this configurable? */
>> +	ap_en = 0;	/* Make this configurable? */
>> +
>> +#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
>> +	/* Use the DDR controller to auto initialize memory. */
>> +	d_init = 1;
>> +	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
>> +	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
>> +#else
>> +	/* Memory will be initialized via DMA, or not at all. */
>> +	d_init = 0;
>> +#endif
>> +
>
> I'm using the current head  
> (33aa4eac66b71c797bbc13b3afe432a2132947d4) on
> a mpc8572-based board.  It uses DDR2 and has support for ECC.  While
> enabling ECC support, I noticed that the "old"
> CONFIG_ECC_INIT_VIA_DDRCONTROLLER define is still being used to enable
> memory initialization on bootup  while a new ECC_init_using_memctl  
> field
> in the memctl_options_s structure is also present.
>
> Currently it looks like ECC_init_using_memctl doesn't do anything  
> and is
> only referenced in one location below:
>
>> +	/* Pick ECC modes */
>> +#ifdef CONFIG_DDR_ECC
>> +	popts->ECC_mode = 1;		  /* 0 = disabled, 1 = enabled */
>> +#else
>> +	popts->ECC_mode = 0;		  /* 0 = disabled, 1 = enabled */
>> +#endif
>> +	popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
>
> The intended functionality of CONFIG_ECC_INIT_VIA_DDRCONTROLLER and
> ECC_init_using_memctl seem to be the same, but only one of them is  
> being
> used, and they currently are unrelated which is a bit confusing.
>
> Should the ECC_init_using_memctl field be removed, or is the intention
> to replace CONFIG_ECC_INIT_VIA_DDRCONTROLLER functionality with
> ECC_init_using_memctl as some point?

Now that the code is unified its will be easier to clean this up.  I  
need to look at the ECC bits a little more to provide a better answer.

- k

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2008-08-29 23:51 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-20 23:22 [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Kumar Gala
2008-08-20 23:22 ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Kumar Gala
2008-08-20 23:22   ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Kumar Gala
2008-08-20 23:22     ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Kumar Gala
2008-08-20 23:22       ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Kumar Gala
2008-08-20 23:22         ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Kumar Gala
2008-08-20 23:22           ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for DDR code Kumar Gala
2008-08-20 23:22             ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN to new " Kumar Gala
2008-08-20 23:22               ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Kumar Gala
2008-08-20 23:22                 ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Kumar Gala
2008-08-20 23:22                   ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Kumar Gala
2008-08-20 23:22                     ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Kumar Gala
2008-08-20 23:22                       ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Kumar Gala
2008-08-20 23:22                         ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Kumar Gala
2008-08-20 23:22                           ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Kumar Gala
2008-08-20 23:22                             ` [U-Boot] [PATCH v3 16/16] FSL DDR: Convert MPC8548CDS " Kumar Gala
2008-08-26 23:13                               ` Wolfgang Denk
2008-08-26 23:13                             ` [U-Boot] [PATCH v3 15/16] FSL DDR: Convert MPC8568MDS " Wolfgang Denk
2008-08-26 23:13                           ` [U-Boot] [PATCH v3 14/16] FSL DDR: Convert MPC8541CDS " Wolfgang Denk
2008-08-26 23:12                         ` [U-Boot] [PATCH v3 13/16] FSL DDR: Convert MPC8555ADS " Wolfgang Denk
2008-08-26 23:12                       ` [U-Boot] [PATCH v3 12/16] FSL DDR: Convert MPC8560ADS " Wolfgang Denk
2008-08-26 23:12                     ` [U-Boot] [PATCH v3 11/16] FSL DDR: Convert MPC8540ADS " Wolfgang Denk
2008-08-26 23:11                   ` [U-Boot] [PATCH v3 10/16] FSL DDR: Convert MPC8544DS " Wolfgang Denk
2008-08-26 23:11                 ` [U-Boot] [PATCH v3 09/16] FSL DDR: Convert MPC8610HPCD " Wolfgang Denk
2008-08-26 23:11               ` [U-Boot] [PATCH v3 08/16] FSL DDR: Convert MPC8641HPCN " Wolfgang Denk
2008-08-26 23:10             ` [U-Boot] [PATCH v3 07/16] FSL DDR: Add e500 TLB helper for " Wolfgang Denk
2008-08-26 23:10           ` [U-Boot] [PATCH v3 06/16] FSL DDR: Provide a generic fsl_ddr_sdram_set_lawbar() Wolfgang Denk
2008-08-26 23:09         ` [U-Boot] [PATCH v3 05/16] FSL DDR: Add interactive DDR config support Wolfgang Denk
2008-08-26 23:08       ` [U-Boot] [PATCH v3 04/16] FSL DDR: Add DDR2 support Wolfgang Denk
2008-08-26 23:08     ` [U-Boot] [PATCH v3 03/16] FSL DDR: Add DDR1 support Wolfgang Denk
2008-08-26 23:08   ` [U-Boot] [PATCH v3 02/16] FSL DDR: Rewrite the FSL mpc8xxx DDR controller setup code Wolfgang Denk
2008-08-29 22:16   ` Peter Tyser
2008-08-29 23:51     ` Kumar Gala
2008-08-26 23:07 ` [U-Boot] [PATCH v3 01/16] Add proper SPD definitions for DDR1/2/3 Wolfgang Denk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox