Skip to content
Snippets Groups Projects
interactive.c 71 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	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");
    }
    #endif
    
    
    #ifdef CONFIG_SYS_FSL_DDR2
    
    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->t_casemax,
    	       " spd->t_casemax,    * 47 t_casemax *");
    	printf("%-3d    : %02x %s\n", 48, spd->psi_ta_dram,
    	       " spd->psi_ta_dram,   * 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->psi_ta_pll,
    	       " spd->psi_ta_pll,    * 58 Thermal Resistance of PLL Package form"
    
    	       " Top (Case) to Ambient (Psi T-A PLL) *");
    
    	printf("%-3d    : %02x %s\n", 59, spd->psi_ta_reg,
    	       " spd->psi_ta_reg,    * 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");
    }
    #endif
    
    
    #ifdef CONFIG_SYS_FSL_DDR3
    
    void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
    {
    	unsigned int i;
    
    	/* General Section: Bytes 0-59 */
    
    
    #define PRINT_NXS(x, y, z...) printf("%-3d    : %02x " z "\n", x, (u8)y);
    
    #define PRINT_NNXXS(n0, n1, x0, x1, s) \
    	printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
    
    	PRINT_NXS(0, spd->info_size_crc,
    		"info_size_crc  bytes written into serial memory, "
    		"CRC coverage");
    	PRINT_NXS(1, spd->spd_rev,
    		"spd_rev        SPD Revision");
    	PRINT_NXS(2, spd->mem_type,
    		"mem_type       Key Byte / DRAM Device Type");
    	PRINT_NXS(3, spd->module_type,
    		"module_type    Key Byte / Module Type");
    	PRINT_NXS(4, spd->density_banks,
    		"density_banks  SDRAM Density and Banks");
    	PRINT_NXS(5, spd->addressing,
    		"addressing     SDRAM Addressing");
    	PRINT_NXS(6, spd->module_vdd,
    		"module_vdd     Module Nominal Voltage, VDD");
    	PRINT_NXS(7, spd->organization,
    		"organization   Module Organization");
    	PRINT_NXS(8, spd->bus_width,
    		"bus_width      Module Memory Bus Width");
    	PRINT_NXS(9, spd->ftb_div,
    		"ftb_div        Fine Timebase (FTB) Dividend / Divisor");
    	PRINT_NXS(10, spd->mtb_dividend,
    		"mtb_dividend   Medium Timebase (MTB) Dividend");
    	PRINT_NXS(11, spd->mtb_divisor,
    		"mtb_divisor    Medium Timebase (MTB) Divisor");
    
    	PRINT_NXS(12, spd->tck_min,
    		  "tck_min        SDRAM Minimum Cycle Time");
    
    	PRINT_NXS(13, spd->res_13,
    		"res_13         Reserved");
    	PRINT_NXS(14, spd->caslat_lsb,
    		"caslat_lsb     CAS Latencies Supported, LSB");
    	PRINT_NXS(15, spd->caslat_msb,
    		"caslat_msb     CAS Latencies Supported, MSB");
    
    	PRINT_NXS(16, spd->taa_min,
    		  "taa_min        Min CAS Latency Time");
    	PRINT_NXS(17, spd->twr_min,
    		  "twr_min        Min Write REcovery Time");
    	PRINT_NXS(18, spd->trcd_min,
    		  "trcd_min       Min RAS# to CAS# Delay Time");
    	PRINT_NXS(19, spd->trrd_min,
    		  "trrd_min       Min Row Active to Row Active Delay Time");
    	PRINT_NXS(20, spd->trp_min,
    		  "trp_min        Min Row Precharge Delay Time");
    	PRINT_NXS(21, spd->tras_trc_ext,
    		  "tras_trc_ext   Upper Nibbles for tRAS and tRC");
    	PRINT_NXS(22, spd->tras_min_lsb,
    		  "tras_min_lsb   Min Active to Precharge Delay Time, LSB");
    	PRINT_NXS(23, spd->trc_min_lsb,
    		  "trc_min_lsb Min Active to Active/Refresh Delay Time, LSB");
    	PRINT_NXS(24, spd->trfc_min_lsb,
    		  "trfc_min_lsb   Min Refresh Recovery Delay Time LSB");
    	PRINT_NXS(25, spd->trfc_min_msb,
    		  "trfc_min_msb   Min Refresh Recovery Delay Time MSB");
    	PRINT_NXS(26, spd->twtr_min,
    		  "twtr_min Min Internal Write to Read Command Delay Time");
    	PRINT_NXS(27, spd->trtp_min,
    		  "trtp_min "
    		  "Min Internal Read to Precharge Command Delay Time");
    	PRINT_NXS(28, spd->tfaw_msb,
    		  "tfaw_msb       Upper Nibble for tFAW");
    	PRINT_NXS(29, spd->tfaw_min,
    		  "tfaw_min       Min Four Activate Window Delay Time");
    
    	PRINT_NXS(30, spd->opt_features,
    		"opt_features   SDRAM Optional Features");
    	PRINT_NXS(31, spd->therm_ref_opt,
    		"therm_ref_opt  SDRAM Thermal and Refresh Opts");
    	PRINT_NXS(32, spd->therm_sensor,
    		"therm_sensor  SDRAM Thermal Sensor");
    	PRINT_NXS(33, spd->device_type,
    		"device_type  SDRAM Device Type");
    
    	PRINT_NXS(34, spd->fine_tck_min,
    		  "fine_tck_min  Fine offset for tCKmin");
    	PRINT_NXS(35, spd->fine_taa_min,
    		  "fine_taa_min  Fine offset for tAAmin");
    	PRINT_NXS(36, spd->fine_trcd_min,
    		  "fine_trcd_min Fine offset for tRCDmin");
    	PRINT_NXS(37, spd->fine_trp_min,
    		  "fine_trp_min  Fine offset for tRPmin");
    	PRINT_NXS(38, spd->fine_trc_min,
    		  "fine_trc_min  Fine offset for tRCmin");
    
    
    	printf("%-3d-%3d: ",  39, 59);  /* Reserved, General Section */
    
    	for (i = 39; i <= 59; i++)
    		printf("%02x ", spd->res_39_59[i - 39]);
    
    
    	puts("\n");
    
    	switch (spd->module_type) {
    	case 0x02:  /* UDIMM */
    	case 0x03:  /* SO-DIMM */
    	case 0x04:  /* Micro-DIMM */
    	case 0x06:  /* Mini-UDIMM */
    		PRINT_NXS(60, spd->mod_section.unbuffered.mod_height,
    			"mod_height    (Unbuffered) Module Nominal Height");
    		PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness,
    			"mod_thickness (Unbuffered) Module Maximum Thickness");
    		PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card,
    			"ref_raw_card  (Unbuffered) Reference Raw Card Used");
    		PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping,
    			"addr_mapping  (Unbuffered) Address mapping from "
    			"Edge Connector to DRAM");
    		break;
    	case 0x01:  /* RDIMM */
    	case 0x05:  /* Mini-RDIMM */
    		PRINT_NXS(60, spd->mod_section.registered.mod_height,
    			"mod_height    (Registered) Module Nominal Height");
    		PRINT_NXS(61, spd->mod_section.registered.mod_thickness,
    			"mod_thickness (Registered) Module Maximum Thickness");
    		PRINT_NXS(62, spd->mod_section.registered.ref_raw_card,
    			"ref_raw_card  (Registered) Reference Raw Card Used");
    		PRINT_NXS(63, spd->mod_section.registered.modu_attr,
    			"modu_attr     (Registered) DIMM Module Attributes");
    		PRINT_NXS(64, spd->mod_section.registered.thermal,
    			"thermal       (Registered) Thermal Heat "
    			"Spreader Solution");
    		PRINT_NXS(65, spd->mod_section.registered.reg_id_lo,
    			"reg_id_lo     (Registered) Register Manufacturer ID "
    			"Code, LSB");
    		PRINT_NXS(66, spd->mod_section.registered.reg_id_hi,
    			"reg_id_hi     (Registered) Register Manufacturer ID "
    			"Code, MSB");
    		PRINT_NXS(67, spd->mod_section.registered.reg_rev,
    			"reg_rev       (Registered) Register "
    			"Revision Number");
    		PRINT_NXS(68, spd->mod_section.registered.reg_type,
    			"reg_type      (Registered) Register Type");
    		for (i = 69; i <= 76; i++) {
    			printf("%-3d    : %02x rcw[%d]\n", i,
    				spd->mod_section.registered.rcw[i-69], i-69);
    		}
    		break;
    	default:
    		/* Module-specific Section, Unsupported Module Type */
    		printf("%-3d-%3d: ", 60, 116);
    
    		for (i = 60; i <= 116; i++)
    			printf("%02x", spd->mod_section.uc[i - 60]);
    
    		break;
    	}
    
    	/* Unique Module ID: Bytes 117-125 */
    	PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
    	PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
    	PRINT_NXS(119, spd->mloc,     "Mfg Location");
    	PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date");
    
    	printf("%-3d-%3d: ", 122, 125);
    
    	for (i = 122; i <= 125; i++)
    		printf("%02x ", spd->sernum[i - 122]);
    	printf("   Module Serial Number\n");
    
    	/* CRC: Bytes 126-127 */
    	PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], "  SPD CRC");
    
    	/* Other Manufacturer Fields and User Space: Bytes 128-255 */
    	printf("%-3d-%3d: ", 128, 145);
    	for (i = 128; i <= 145; i++)
    		printf("%02x ", spd->mpart[i - 128]);
    	printf("   Mfg's Module Part Number\n");
    
    	PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1],
    		"Module Revision code");
    
    	PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
    	PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
    
    	printf("%-3d-%3d: ", 150, 175);
    	for (i = 150; i <= 175; i++)
    		printf("%02x ", spd->msd[i - 150]);
    	printf("   Mfg's Specific Data\n");
    
    	printf("%-3d-%3d: ", 176, 255);
    	for (i = 176; i <= 255; i++)
    		printf("%02x", spd->cust[i - 176]);
    	printf("   Mfg's Specific Data\n");
    
    }
    #endif
    
    
    #ifdef CONFIG_SYS_FSL_DDR4
    void ddr4_spd_dump(const struct ddr4_spd_eeprom_s *spd)
    {
    	unsigned int i;
    
    	/* General Section: Bytes 0-127 */
    
    #define PRINT_NXS(x, y, z...) printf("%-3d    : %02x " z "\n", x, (u8)y);
    #define PRINT_NNXXS(n0, n1, x0, x1, s) \
    	printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
    
    	PRINT_NXS(0, spd->info_size_crc,
    		  "info_size_crc  bytes written into serial memory, CRC coverage");
    	PRINT_NXS(1, spd->spd_rev,
    		  "spd_rev        SPD Revision");
    	PRINT_NXS(2, spd->mem_type,
    		  "mem_type       Key Byte / DRAM Device Type");
    	PRINT_NXS(3, spd->module_type,
    		  "module_type    Key Byte / Module Type");
    	PRINT_NXS(4, spd->density_banks,
    		  "density_banks  SDRAM Density and Banks");
    	PRINT_NXS(5, spd->addressing,
    		  "addressing     SDRAM Addressing");
    	PRINT_NXS(6, spd->package_type,
    		  "package_type   Package type");
    	PRINT_NXS(7, spd->opt_feature,
    		  "opt_feature    Optional features");
    	PRINT_NXS(8, spd->thermal_ref,
    		  "thermal_ref    Thermal and Refresh options");
    	PRINT_NXS(9, spd->oth_opt_features,
    		  "oth_opt_features Other SDRAM optional features");
    	PRINT_NXS(10, spd->res_10,
    		  "res_10         Reserved");
    	PRINT_NXS(11, spd->module_vdd,
    		  "module_vdd     Module Nominal Voltage, VDD");
    	PRINT_NXS(12, spd->organization,
    		  "organization Module Organization");
    	PRINT_NXS(13, spd->bus_width,
    		  "bus_width      Module Memory Bus Width");
    	PRINT_NXS(14, spd->therm_sensor,
    		  "therm_sensor   Module Thermal Sensor");
    	PRINT_NXS(15, spd->ext_type,
    		  "ext_type       Extended module type");
    	PRINT_NXS(16, spd->res_16,
    		  "res_16       Reserved");
    	PRINT_NXS(17, spd->timebases,
    		  "timebases    MTb and FTB");
    	PRINT_NXS(18, spd->tck_min,
    		  "tck_min      tCKAVGmin");
    	PRINT_NXS(19, spd->tck_max,
    		  "tck_max      TCKAVGmax");
    	PRINT_NXS(20, spd->caslat_b1,
    		  "caslat_b1    CAS latencies, 1st byte");
    	PRINT_NXS(21, spd->caslat_b2,
    		  "caslat_b2    CAS latencies, 2nd byte");
    	PRINT_NXS(22, spd->caslat_b3,
    		  "caslat_b3    CAS latencies, 3rd byte ");
    	PRINT_NXS(23, spd->caslat_b4,
    		  "caslat_b4    CAS latencies, 4th byte");
    	PRINT_NXS(24, spd->taa_min,
    		  "taa_min      Min CAS Latency Time");
    	PRINT_NXS(25, spd->trcd_min,
    		  "trcd_min     Min RAS# to CAS# Delay Time");
    	PRINT_NXS(26, spd->trp_min,
    		  "trp_min      Min Row Precharge Delay Time");
    	PRINT_NXS(27, spd->tras_trc_ext,
    		  "tras_trc_ext Upper Nibbles for tRAS and tRC");
    	PRINT_NXS(28, spd->tras_min_lsb,
    		  "tras_min_lsb tRASmin, lsb");
    	PRINT_NXS(29, spd->trc_min_lsb,
    		  "trc_min_lsb  tRCmin, lsb");
    	PRINT_NXS(30, spd->trfc1_min_lsb,
    		  "trfc1_min_lsb  Min Refresh Recovery Delay Time, LSB");
    	PRINT_NXS(31, spd->trfc1_min_msb,
    		  "trfc1_min_msb  Min Refresh Recovery Delay Time, MSB ");
    	PRINT_NXS(32, spd->trfc2_min_lsb,
    		  "trfc2_min_lsb  Min Refresh Recovery Delay Time, LSB");
    	PRINT_NXS(33, spd->trfc2_min_msb,
    		  "trfc2_min_msb  Min Refresh Recovery Delay Time, MSB");
    	PRINT_NXS(34, spd->trfc4_min_lsb,
    		  "trfc4_min_lsb Min Refresh Recovery Delay Time, LSB");
    	PRINT_NXS(35, spd->trfc4_min_msb,
    		  "trfc4_min_msb Min Refresh Recovery Delay Time, MSB");
    	PRINT_NXS(36, spd->tfaw_msb,
    		  "tfaw_msb      Upper Nibble for tFAW");
    	PRINT_NXS(37, spd->tfaw_min,
    		  "tfaw_min      tFAW, lsb");
    	PRINT_NXS(38, spd->trrds_min,
    		  "trrds_min     tRRD_Smin, MTB");
    	PRINT_NXS(39, spd->trrdl_min,
    		  "trrdl_min     tRRD_Lmin, MTB");
    	PRINT_NXS(40, spd->tccdl_min,
    		  "tccdl_min     tCCS_Lmin, MTB");
    
    	printf("%-3d-%3d: ", 41, 59);  /* Reserved, General Section */
    	for (i = 41; i <= 59; i++)
    		printf("%02x ", spd->res_41[i - 41]);
    
    	puts("\n");
    	printf("%-3d-%3d: ", 60, 77);
    	for (i = 60; i <= 77; i++)
    		printf("%02x ", spd->mapping[i - 60]);
    	puts("   mapping[] Connector to SDRAM bit map\n");
    
    	PRINT_NXS(117, spd->fine_tccdl_min,
    		  "fine_tccdl_min Fine offset for tCCD_Lmin");
    	PRINT_NXS(118, spd->fine_trrdl_min,
    		  "fine_trrdl_min Fine offset for tRRD_Lmin");
    	PRINT_NXS(119, spd->fine_trrds_min,
    		  "fine_trrds_min Fine offset for tRRD_Smin");
    	PRINT_NXS(120, spd->fine_trc_min,
    		  "fine_trc_min   Fine offset for tRCmin");
    	PRINT_NXS(121, spd->fine_trp_min,
    		  "fine_trp_min   Fine offset for tRPmin");
    	PRINT_NXS(122, spd->fine_trcd_min,
    		  "fine_trcd_min  Fine offset for tRCDmin");
    	PRINT_NXS(123, spd->fine_taa_min,
    		  "fine_taa_min   Fine offset for tAAmin");
    	PRINT_NXS(124, spd->fine_tck_max,
    		  "fine_tck_max   Fine offset for tCKAVGmax");
    	PRINT_NXS(125, spd->fine_tck_min,
    		  "fine_tck_min   Fine offset for tCKAVGmin");
    
    	/* CRC: Bytes 126-127 */
    	PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], "  SPD CRC");
    
    	switch (spd->module_type) {
    	case 0x02:  /* UDIMM */
    	case 0x03:  /* SO-DIMM */
    		PRINT_NXS(128, spd->mod_section.unbuffered.mod_height,
    			  "mod_height    (Unbuffered) Module Nominal Height");
    		PRINT_NXS(129, spd->mod_section.unbuffered.mod_thickness,
    			  "mod_thickness (Unbuffered) Module Maximum Thickness");
    		PRINT_NXS(130, spd->mod_section.unbuffered.ref_raw_card,
    			  "ref_raw_card  (Unbuffered) Reference Raw Card Used");
    		PRINT_NXS(131, spd->mod_section.unbuffered.addr_mapping,
    			  "addr_mapping  (Unbuffered) Address mapping from Edge Connector to DRAM");
    		PRINT_NNXXS(254, 255, spd->mod_section.unbuffered.crc[0],
    			    spd->mod_section.unbuffered.crc[1], "  Module CRC");
    		break;
    	case 0x01:  /* RDIMM */
    		PRINT_NXS(128, spd->mod_section.registered.mod_height,
    			  "mod_height    (Registered) Module Nominal Height");
    		PRINT_NXS(129, spd->mod_section.registered.mod_thickness,
    			  "mod_thickness (Registered) Module Maximum Thickness");
    		PRINT_NXS(130, spd->mod_section.registered.ref_raw_card,
    			  "ref_raw_card  (Registered) Reference Raw Card Used");
    		PRINT_NXS(131, spd->mod_section.registered.modu_attr,
    			  "modu_attr     (Registered) DIMM Module Attributes");
    		PRINT_NXS(132, spd->mod_section.registered.thermal,
    			  "thermal       (Registered) Thermal Heat Spreader Solution");
    		PRINT_NXS(133, spd->mod_section.registered.reg_id_lo,
    			  "reg_id_lo     (Registered) Register Manufacturer ID Code, LSB");
    		PRINT_NXS(134, spd->mod_section.registered.reg_id_hi,
    			  "reg_id_hi     (Registered) Register Manufacturer ID Code, MSB");
    		PRINT_NXS(135, spd->mod_section.registered.reg_rev,
    			  "reg_rev       (Registered) Register Revision Number");
    		PRINT_NXS(136, spd->mod_section.registered.reg_map,
    			  "reg_map       (Registered) Address mapping");
    		PRINT_NNXXS(254, 255, spd->mod_section.registered.crc[0],
    			    spd->mod_section.registered.crc[1], "  Module CRC");
    		break;
    	case 0x04:  /* LRDIMM */
    		PRINT_NXS(128, spd->mod_section.loadreduced.mod_height,
    			  "mod_height    (Loadreduced) Module Nominal Height");
    		PRINT_NXS(129, spd->mod_section.loadreduced.mod_thickness,
    			  "mod_thickness (Loadreduced) Module Maximum Thickness");
    		PRINT_NXS(130, spd->mod_section.loadreduced.ref_raw_card,
    			  "ref_raw_card  (Loadreduced) Reference Raw Card Used");
    		PRINT_NXS(131, spd->mod_section.loadreduced.modu_attr,
    			  "modu_attr     (Loadreduced) DIMM Module Attributes");
    		PRINT_NXS(132, spd->mod_section.loadreduced.thermal,
    			  "thermal       (Loadreduced) Thermal Heat Spreader Solution");
    		PRINT_NXS(133, spd->mod_section.loadreduced.reg_id_lo,
    			  "reg_id_lo     (Loadreduced) Register Manufacturer ID Code, LSB");
    		PRINT_NXS(134, spd->mod_section.loadreduced.reg_id_hi,
    			  "reg_id_hi     (Loadreduced) Register Manufacturer ID Code, MSB");
    		PRINT_NXS(135, spd->mod_section.loadreduced.reg_rev,
    			  "reg_rev       (Loadreduced) Register Revision Number");
    		PRINT_NXS(136, spd->mod_section.loadreduced.reg_map,
    			  "reg_map       (Loadreduced) Address mapping");
    		PRINT_NXS(137, spd->mod_section.loadreduced.reg_drv,
    			  "reg_drv       (Loadreduced) Reg output drive strength");
    		PRINT_NXS(138, spd->mod_section.loadreduced.reg_drv_ck,
    			  "reg_drv_ck    (Loadreduced) Reg output drive strength for CK");
    		PRINT_NXS(139, spd->mod_section.loadreduced.data_buf_rev,
    			  "data_buf_rev  (Loadreduced) Data Buffer Revision Numbe");
    		PRINT_NXS(140, spd->mod_section.loadreduced.vrefqe_r0,
    			  "vrefqe_r0     (Loadreduced) DRAM VrefDQ for Package Rank 0");
    		PRINT_NXS(141, spd->mod_section.loadreduced.vrefqe_r1,
    			  "vrefqe_r1     (Loadreduced) DRAM VrefDQ for Package Rank 1");
    		PRINT_NXS(142, spd->mod_section.loadreduced.vrefqe_r2,
    			  "vrefqe_r2     (Loadreduced) DRAM VrefDQ for Package Rank 2");
    		PRINT_NXS(143, spd->mod_section.loadreduced.vrefqe_r3,
    			  "vrefqe_r3     (Loadreduced) DRAM VrefDQ for Package Rank 3");
    		PRINT_NXS(144, spd->mod_section.loadreduced.data_intf,
    			  "data_intf     (Loadreduced) Data Buffer VrefDQ for DRAM Interface");
    		PRINT_NXS(145, spd->mod_section.loadreduced.data_drv_1866,
    			  "data_drv_1866 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
    		PRINT_NXS(146, spd->mod_section.loadreduced.data_drv_2400,
    			  "data_drv_2400 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
    		PRINT_NXS(147, spd->mod_section.loadreduced.data_drv_3200,
    			  "data_drv_3200 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
    		PRINT_NXS(148, spd->mod_section.loadreduced.dram_drv,
    			  "dram_drv      (Loadreduced) DRAM Drive Strength");
    		PRINT_NXS(149, spd->mod_section.loadreduced.dram_odt_1866,
    			  "dram_odt_1866 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
    		PRINT_NXS(150, spd->mod_section.loadreduced.dram_odt_2400,
    			  "dram_odt_2400 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
    		PRINT_NXS(151, spd->mod_section.loadreduced.dram_odt_3200,
    			  "dram_odt_3200 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
    		PRINT_NXS(152, spd->mod_section.loadreduced.dram_odt_park_1866,
    			  "dram_odt_park_1866 (Loadreduced) DRAM ODT (RTT_PARK)");
    		PRINT_NXS(153, spd->mod_section.loadreduced.dram_odt_park_2400,
    			  "dram_odt_park_2400 (Loadreduced) DRAM ODT (RTT_PARK)");
    		PRINT_NXS(154, spd->mod_section.loadreduced.dram_odt_park_3200,
    			  "dram_odt_park_3200 (Loadreduced) DRAM ODT (RTT_PARK)");
    		PRINT_NNXXS(254, 255, spd->mod_section.loadreduced.crc[0],
    			    spd->mod_section.loadreduced.crc[1],
    			    "  Module CRC");
    		break;
    	default:
    		/* Module-specific Section, Unsupported Module Type */
    		printf("%-3d-%3d: ", 128, 255);
    
    		for (i = 128; i <= 255; i++)
    
    			printf("%02x", spd->mod_section.uc[i - 128]);
    
    
    		break;
    	}
    
    	/* Unique Module ID: Bytes 320-383 */
    	PRINT_NXS(320, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
    	PRINT_NXS(321, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
    	PRINT_NXS(322, spd->mloc,     "Mfg Location");
    	PRINT_NNXXS(323, 324, spd->mdate[0], spd->mdate[1], "Mfg Date");
    
    	printf("%-3d-%3d: ", 325, 328);
    
    	for (i = 325; i <= 328; i++)
    		printf("%02x ", spd->sernum[i - 325]);
    	printf("   Module Serial Number\n");
    
    	printf("%-3d-%3d: ", 329, 348);
    	for (i = 329; i <= 348; i++)
    		printf("%02x ", spd->mpart[i - 329]);
    	printf("   Mfg's Module Part Number\n");
    
    	PRINT_NXS(349, spd->mrev, "Module Revision code");
    	PRINT_NXS(350, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
    	PRINT_NXS(351, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
    	PRINT_NXS(352, spd->stepping, "DRAM stepping");
    
    	printf("%-3d-%3d: ", 353, 381);
    	for (i = 353; i <= 381; i++)
    		printf("%02x ", spd->msd[i - 353]);
    	printf("   Mfg's Specific Data\n");
    }
    #endif
    
    
    static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
    {
    
    #if defined(CONFIG_SYS_FSL_DDR1)
    
    #elif defined(CONFIG_SYS_FSL_DDR2)
    
    #elif defined(CONFIG_SYS_FSL_DDR3)
    
    #elif defined(CONFIG_SYS_FSL_DDR4)
    	ddr4_spd_dump(spd);
    
    #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;
    
    			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");
    	}
    }
    
    struct data_strings {
    	const char *data_name;
    	unsigned int step_mask;
    	unsigned int dimm_number_required;
    };
    
    #define DATA_OPTIONS(name, step, dimm) {#name, step, dimm}
    
    
    static unsigned int fsl_ddr_parse_interactive_cmd(
    	char **argv,
    	int argc,
    	unsigned int *pstep_mask,
    	unsigned int *pctlr_mask,
    	unsigned int *pdimm_mask,
    	unsigned int *pdimm_number_required
    	 ) {
    
    
    	static const struct data_strings options[] = {
    		DATA_OPTIONS(spd, STEP_GET_SPD, 1),
    		DATA_OPTIONS(dimmparms, STEP_COMPUTE_DIMM_PARMS, 1),
    		DATA_OPTIONS(commonparms, STEP_COMPUTE_COMMON_PARMS, 0),
    		DATA_OPTIONS(opts, STEP_GATHER_OPTS, 0),
    		DATA_OPTIONS(addresses, STEP_ASSIGN_ADDRESSES, 0),
    		DATA_OPTIONS(regs, STEP_COMPUTE_REGS, 0),
    	};
    	static const unsigned int n_opts = ARRAY_SIZE(options);
    
    
    	unsigned int i, j;
    	unsigned int error = 0;
    
    	for (i = 1; i < argc; i++) {
    
    		unsigned int matched = 0;
    
    
    		for (j = 0; j < n_opts; j++) {
    			if (strcmp(options[j].data_name, argv[i]) != 0)
    				continue;
    			*pstep_mask |= options[j].step_mask;
    			*pdimm_number_required =
    				options[j].dimm_number_required;
    			matched = 1;
    			break;
    		}
    
    		if (matched)
    			continue;
    
    		if (argv[i][0] == 'c') {
    			char c = argv[i][1];
    			if (isdigit(c))
    				*pctlr_mask |= 1 << (c - '0');
    			continue;
    		}
    
    		if (argv[i][0] == 'd') {
    			char c = argv[i][1];
    			if (isdigit(c))
    				*pdimm_mask |= 1 << (c - '0');
    			continue;
    		}
    
    		printf("unknown arg %s\n", argv[i]);
    		*pstep_mask = 0;
    		error = 1;
    		break;
    	}
    
    	return error;
    }
    
    
    int fsl_ddr_interactive_env_var_exists(void)
    {
    	char buffer[CONFIG_SYS_CBSIZE];
    
    	if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0)
    		return 1;
    
    	return 0;
    }
    
    unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set)
    
    {
    	unsigned long long ddrsize;
    	const char *prompt = "FSL DDR>";
    	char buffer[CONFIG_SYS_CBSIZE];
    
    	char buffer2[CONFIG_SYS_CBSIZE];
    	char *p = NULL;
    
    	char *argv[CONFIG_SYS_MAXARGS + 1];	/* NULL terminated */
    	int argc;
    	unsigned int next_step = STEP_GET_SPD;
    
    	const char *usage = {
    		"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"
    		"edit       modify spd, parameter, or option\n"
    		"compute    recompute registers from current next_step to end\n"
    
    		"copy       copy parameters\n"
    
    		"next_step  shows current next_step\n"
    		"help       this message\n"
    		"go         program the memory controller and continue with u-boot\n"
    	};
    
    
    	if (var_is_set) {
    		if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) {
    			p = buffer2;
    		} else {
    			var_is_set = 0;
    		}
    	}
    
    
    	/*
    	 * The strategy for next_step is that it points to the next
    	 * step in the computation process that needs to be done.
    	 */
    	while (1) {
    
    		if (var_is_set) {
    			char *pend = strchr(p, ';');
    			if (pend) {
    				/* found command separator, copy sub-command */
    				*pend = '\0';
    				strcpy(buffer, p);
    				p = pend + 1;
    			} else {
    				/* separator not found, copy whole string */
    				strcpy(buffer, p);
    				p = NULL;
    				var_is_set = 0;
    			}
    		} else {
    			/*
    			 * No need to worry for buffer overflow here in
    
    			 * this function;  cli_readline() maxes out at
    			 * CFG_CBSIZE
    
    			cli_readline_into_buffer(prompt, buffer, 0);
    
    		argc = cli_simple_parse_line(buffer, argv);
    
    		if (argc == 0)
    			continue;
    
    
    		if (strcmp(argv[0], "help") == 0) {
    			puts(usage);
    			continue;
    		}
    
    		if (strcmp(argv[0], "next_step") == 0) {
    			printf("next_step = 0x%02X (%s)\n",
    			       next_step,
    			       step_to_string(next_step));
    			continue;
    		}
    
    
    		if (strcmp(argv[0], "copy") == 0) {
    			unsigned int error = 0;
    			unsigned int step_mask = 0;
    			unsigned int src_ctlr_mask = 0;
    			unsigned int src_dimm_mask = 0;
    			unsigned int dimm_number_required = 0;
    			unsigned int src_ctlr_num = 0;
    			unsigned int src_dimm_num = 0;
    			unsigned int dst_ctlr_num = -1;
    			unsigned int dst_dimm_num = -1;
    			unsigned int i, num_dest_parms;
    
    			if (argc == 1) {
    				printf("copy <src c#> <src d#> <spd|dimmparms|commonparms|opts|addresses|regs> <dst c#> <dst d#>\n");
    				continue;
    			}
    
    			error = fsl_ddr_parse_interactive_cmd(
    				argv, argc,
    				&step_mask,
    				&src_ctlr_mask,
    				&src_dimm_mask,
    				&dimm_number_required
    			);
    
    			/* XXX: only dimm_number_required and step_mask will
    			   be used by this function.  Parse the controller and
    			   DIMM number separately because it is easier.  */
    
    			if (error)
    				continue;
    
    			/* parse source destination controller / DIMM */
    
    			num_dest_parms = dimm_number_required ? 2 : 1;
    
    			for (i = 0; i < argc; i++) {
    				if (argv[i][0] == 'c') {
    					char c = argv[i][1];
    					if (isdigit(c)) {
    						src_ctlr_num = (c - '0');
    						break;
    					}
    				}
    			}
    
    			for (i = 0; i < argc; i++) {
    				if (argv[i][0] == 'd') {
    					char c = argv[i][1];
    					if (isdigit(c)) {
    						src_dimm_num = (c - '0');
    						break;
    					}
    				}
    			}
    
    			/* parse destination controller / DIMM */
    
    			for (i = argc - 1; i >= argc - num_dest_parms; i--) {
    				if (argv[i][0] == 'c') {
    					char c = argv[i][1];