summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/hosttools/memconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/hosttools/memconfig.c')
-rw-r--r--cfe/cfe/hosttools/memconfig.c654
1 files changed, 654 insertions, 0 deletions
diff --git a/cfe/cfe/hosttools/memconfig.c b/cfe/cfe/hosttools/memconfig.c
new file mode 100644
index 0000000..3d84b05
--- /dev/null
+++ b/cfe/cfe/hosttools/memconfig.c
@@ -0,0 +1,654 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Memory Config Utility File: memconfig.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This host tool lets you enter DRAM parameters and run CFE's
+ * standard memory configuration to calculate the relevant timing
+ * parameters. It's a good way to see what CFE would have done,
+ * to find bogus timing calculations.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdio.h>
+#include <string.h>
+
+/* *********************************************************************
+ * Basic types
+ ********************************************************************* */
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+/* *********************************************************************
+ * SB1250 stuff
+ ********************************************************************* */
+
+#include "sb1250_defs.h"
+#include "sb1250_mc.h"
+#include "sb1250_draminit.h"
+#include "sb1250_regs.h"
+#include "sb1250_scd.h"
+
+/* *********************************************************************
+ * BCD macros
+ ********************************************************************* */
+
+#define DECTO10THS(x) ((((x) >> 4)*10)+((x) & 0x0F))
+
+/* *********************************************************************
+ * Global defaults
+ ********************************************************************* */
+
+#define MIN_tMEMCLK DRT10(8,0)
+#define tROUNDTRIP DRT10(2,5)
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct encvalue_s {
+ char *name;
+ uint8_t val;
+} encvalue_t;
+
+typedef struct spdbyte_s {
+ char *name;
+ uint8_t *data;
+ int decimal;
+ encvalue_t *values;
+ char *units;
+ char *description;
+ char *deflt;
+} spdbyte_t;
+
+#define SPD_DEC_BCD 1
+#define SPD_DEC_QTR 2
+#define SPD_ENCODED 3
+#define SPD_ENCODED2 4
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+
+uint8_t spd[64] = {0}; /* SPD data */
+uint8_t mintmemclk = MIN_tMEMCLK; /* Default value: 8.0ns */
+uint8_t roundtrip = tROUNDTRIP; /* Default value: 2.5ns */
+uint8_t dramtype = JEDEC; /* Regular DDR SDRAMs */
+uint8_t plldiv = 10; /* 500 MHz using 100Mhz refclk */
+uint8_t refclk = 100; /* 100Mhz reference clock */
+uint8_t portintlv = 0; /* no port interleaving */
+
+uint8_t addrskew = 0xF;
+uint8_t dqoskew = 0x8;
+uint8_t dqiskew = 0x8;
+uint8_t addrdrive = 0xF;
+uint8_t datadrive = 0xF;
+uint8_t clkdrive = 0;
+
+uint64_t mc0_mclkcfg; /* Value programmed by draminit */
+uint64_t mc0_timing1; /* Value programmed by draminit */
+uint64_t smbus0_start = 0; /* Rememberd SMBus register value */
+uint64_t smbus0_cmd = 0; /* Rememberd SMBus register value */
+
+extern int sb1250_refclk; /* from draminit - reference clock */
+extern int dram_cas_latency; /* from draminit - calc'd cas latency */
+extern int dram_tMemClk; /* from draminit - calc'd tMemClk */
+
+draminittab_t inittab[16]; /* our init tab */
+
+int debug = 0;
+
+/* *********************************************************************
+ * Parameter and value tables
+ ********************************************************************* */
+
+encvalue_t caslatencies[] = {
+ {"3.5",JEDEC_CASLAT_35},
+ {"3.0",JEDEC_CASLAT_30},
+ {"2.5",JEDEC_CASLAT_25},
+ {"2.0",JEDEC_CASLAT_20},
+ {"1.5",JEDEC_CASLAT_15},
+ {"1.0",JEDEC_CASLAT_10},
+ {NULL,0}};
+
+encvalue_t refreshrates[] = {
+ {"64",JEDEC_RFSH_64khz},
+ {"256",JEDEC_RFSH_256khz},
+ {"128",JEDEC_RFSH_128khz},
+ {"32",JEDEC_RFSH_32khz},
+ {"16",JEDEC_RFSH_16khz},
+ {"8",JEDEC_RFSH_8khz},
+ {NULL,0}};
+
+encvalue_t modattribs[] = {
+ {"none",0},
+ {"reg",JEDEC_ATTRIB_REG},
+ {"diffclk",0x20},
+ {NULL,0}};
+
+encvalue_t dramtypes[] = {
+ {"jedec",JEDEC},
+ {"fcram",FCRAM},
+ {"sgram",SGRAM},
+ {NULL,0}};
+
+spdbyte_t spdfields[] = {
+ {"mintmemclk",&mintmemclk,SPD_DEC_BCD,NULL,"ns","Minimum value for tMEMCLK","8.0"},
+ {"roundtrip", &roundtrip, SPD_DEC_BCD,NULL,"ns","Round trip time from CLK to returned DQS","2.5"},
+ {"plldiv", &plldiv, 0,NULL,"","PLL Ratio (System Config Register)","10"},
+ {"refclk", &refclk, 0,NULL,"Mhz","Reference clock, usually 100Mhz","100"},
+// {"portintlv", &portintlv, 0,NULL,"","Port interleave (1=on)","0"},
+ {"memtype", &dramtype, SPD_ENCODED,dramtypes,"","Memory type (jedec, fcram, sgram)","jedec"},
+ {"rows", &spd[JEDEC_SPD_ROWS],0,NULL,"","[3 ] Number of row bits","13"},
+ {"cols", &spd[JEDEC_SPD_COLS],0,NULL,"","[4 ] Number of column bits","9"},
+ {"banks", &spd[JEDEC_SPD_BANKS],0,NULL,"","[17] Number of banks","4"},
+ {"tCK25", &spd[JEDEC_SPD_tCK25],SPD_DEC_BCD,NULL,"ns","[9 ] tCK value for CAS Latency 2.5","7.5"},
+ {"tCK20", &spd[JEDEC_SPD_tCK20],SPD_DEC_BCD,NULL,"ns","[23] tCK value for CAS Latency 2.0","0"},
+ {"tCK10", &spd[JEDEC_SPD_tCK10],SPD_DEC_BCD,NULL,"ns","[25] tCK value for CAS Latency 1.0","0"},
+ {"rfsh", &spd[JEDEC_SPD_RFSH],SPD_ENCODED,refreshrates,"","[12] Refresh rate (KHz)","8"},
+ {"caslat", &spd[JEDEC_SPD_CASLATENCIES],SPD_ENCODED2,caslatencies,"","[18] CAS Latencies supported","2.5"},
+ {"attrib", &spd[JEDEC_SPD_ATTRIBUTES],SPD_ENCODED,modattribs,"","[21] Module attributes","none"},
+ {"tRAS", &spd[JEDEC_SPD_tRAS],0,NULL,"ns","[30]","45"},
+ {"tRP", &spd[JEDEC_SPD_tRP],SPD_DEC_QTR,NULL,"ns","[27]","20.0"},
+ {"tRRD", &spd[JEDEC_SPD_tRRD],SPD_DEC_QTR,NULL,"ns","[28]","15.0"},
+ {"tRCD", &spd[JEDEC_SPD_tRCD],SPD_DEC_QTR,NULL,"ns","[29]","20.0"},
+ {"tRFC", &spd[JEDEC_SPD_tRFC],0,NULL,"ns","[42]","0"},
+ {"tRC", &spd[JEDEC_SPD_tRC],0,NULL,"ns","[41]","0"},
+
+ {"addrskew", &addrskew, 0, NULL, "","Address Skew","0x0F"},
+ {"dqoskew", &dqoskew, 0, NULL, "","DQO Skew","0x08"},
+ {"dqikew", &dqiskew, 0, NULL, "","DQI Skew","0x08"},
+ {"addrdrive", &addrdrive, 0, NULL, "","Address Drive","0x0F"},
+ {"datadrive", &datadrive, 0, NULL, "","Data Drive","0x0F"},
+ {"clkdrive", &clkdrive, 0, NULL, "","Clock Drive","0"},
+ {NULL,0,0,NULL,NULL,NULL,NULL}};
+
+char *lookupstr(encvalue_t *ev,uint8_t val)
+{
+ while (ev->name) {
+ if (ev->val == val) return ev->name;
+ ev++;
+ }
+ return "unknown";
+}
+
+uint64_t sbreadcsr(uint64_t reg)
+{
+ uint64_t val = 0;
+
+ if (debug) printf("READ %08X\n",(uint32_t) reg);
+
+ switch ((uint32_t) reg) {
+ case A_SCD_SYSTEM_REVISION:
+ val = V_SYS_PART(0x1250) | V_SYS_WID(0) | V_SYS_REVISION(1) | 0xFF;
+ break;
+ case A_SCD_SYSTEM_CFG:
+ val = V_SYS_PLL_DIV(plldiv);
+ break;
+ case A_SMB_STATUS_0:
+ val = 0;
+ break;
+ case A_SMB_CMD_0:
+ val = smbus0_cmd;
+ break;
+ case A_SMB_START_0:
+ val = smbus0_start;
+ break;
+ case A_SMB_DATA_0:
+ val = spd[smbus0_cmd & 0x3F];
+ break;
+ }
+ return val;
+}
+
+void sbwritecsr(uint64_t reg,uint64_t val)
+{
+ if (debug) printf("WRITE %08X %016llX\n",(uint32_t) reg,val);
+
+ switch ((uint32_t) reg) {
+ case A_MC_REGISTER(0,R_MC_MCLK_CFG):
+ mc0_mclkcfg = val;
+ break;
+ case A_MC_REGISTER(0,R_MC_TIMING1):
+ mc0_timing1 = val;
+ break;
+ case A_SMB_CMD_0:
+ smbus0_cmd = val;
+ break;
+ case A_SMB_START_0:
+ smbus0_start = val;
+ break;
+ }
+}
+
+
+int procfield(char *txt)
+{
+ int num = 0;
+ int a,b;
+ spdbyte_t *sf;
+ encvalue_t *ev;
+ char *x;
+ char *tok;
+
+ x = strchr(txt,'=');
+ if (!x) {
+ printf("Fields must be specified as 'name=value'\n");
+ exit(1);
+ }
+ *x++ = '\0';
+
+ sf = spdfields;
+ while (sf->name) {
+ if (strcmp(sf->name,txt) == 0) break;
+ sf++;
+ }
+
+ if (sf->name == NULL) {
+ printf("Invalid field name: %s\n",txt);
+ return -1;
+ }
+
+ if (memcmp(x,"0x",2) == 0) {
+ sscanf(x+2,"%x",&num);
+ }
+ else {
+ if (strchr(x,'.')) {
+ if (sscanf(x,"%d.%d",&a,&b) != 2) {
+ printf("%s: invalid number: %s\n",sf->name,x);
+ return -1;
+ }
+ }
+ else {
+ a = atoi(x);
+ b = 0;
+ }
+
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ if ((b < 0) || (b > 9)) {
+ printf("%s: Invalid BCD number: %s\n",sf->name,x);
+ return -1;
+ }
+ num = (a*16)+b;
+ break;
+ case SPD_DEC_QTR:
+ if ((b != 0) && (b != 25) && (b != 50) && (b != 75)) {
+ printf("%s: Invalid 2-bit fraction number: %s\n",sf->name,x);
+ printf("(number after decimal should be 0,25,50,75)\n");
+ exit(1);
+ }
+ num = (a*4)+(b/25);
+ break;
+ case SPD_ENCODED:
+ ev = sf->values;
+ while (ev->name) {
+ if (strcmp(ev->name,x) == 0) break;
+ ev++;
+ }
+ if (!ev->name) {
+ printf("%s: Invalid value. Valid values are: ",x);
+ ev = sf->values;
+ while (ev->name) { printf("%s ",ev->name); ev++; }
+ printf("\n");
+ return -1;
+ }
+ num = ev->val;
+ break;
+ case SPD_ENCODED2:
+ tok = strtok(x," ,");
+ num = 0;
+ while (tok) {
+ ev = sf->values;
+ while (ev->name) {
+ if (strcmp(ev->name,tok) == 0) break;
+ ev++;
+ }
+ if (!ev->name) {
+ printf("%s: Invalid value. Valid values are: ",tok);
+ ev = sf->values;
+ while (ev->name) { printf("%s ",ev->name); ev++; }
+ printf("\n");
+ return -1;
+ }
+ num |= ev->val;
+ tok = strtok(NULL," ,");
+ }
+ break;
+ default:
+ num = a;
+ break;
+ }
+ }
+
+ *(sf->data) = num;
+
+ return 0;
+}
+
+void interactive(void)
+{
+ spdbyte_t *sf;
+ char field[100];
+ char ask[100];
+ char prompt[100];
+ char *x;
+
+ sf = spdfields;
+
+ printf("%-65.65s: Value\n","Parameter");
+ printf("%-65.65s: -----\n","-----------------------------------------------------------------");
+
+ while (sf->name) {
+ for (;;) {
+ x = prompt;
+ x += sprintf(x,"%s (%s", sf->name,sf->description);
+ if (sf->units && sf->units[0]) {
+ if (sf->description && sf->description[0]) x += sprintf(x,", ");
+ x += sprintf(x,"%s",sf->units);
+ }
+ x += sprintf(x,"): [%s]", sf->deflt);
+ printf("%-65.65s: ",prompt);
+
+ fgets(ask,sizeof(ask),stdin);
+ if ((x = strchr(ask,'\n'))) *x = '\0';
+ if (ask[0] == 0) strcpy(ask,sf->deflt);
+ sprintf(field,"%s=%s",sf->name,ask);
+ if (procfield(field) < 0) continue;
+ break;
+ }
+ sf++;
+ }
+
+ printf("\n\n");
+}
+
+int swcnt = 0;
+char *swnames[32];
+
+int proc_args(int argc,char *argv[])
+{
+ int inidx,outidx;
+
+ outidx = 1;
+
+ for (inidx = 1; inidx < argc; inidx++) {
+ if (argv[inidx][0] != '-') {
+ argv[outidx++] = argv[inidx];
+ }
+ else {
+ swnames[swcnt] = argv[inidx];
+ swcnt++;
+ }
+ }
+
+ return outidx;
+}
+
+int swisset(char *x)
+{
+ int idx;
+
+ for (idx = 0; idx < swcnt; idx++) {
+ if (strcmp(x,swnames[idx]) == 0) return 1;
+ }
+ return 0;
+}
+
+void dumpmclkcfg(uint64_t val)
+{
+ printf("clk_ratio = %d\n",G_MC_CLK_RATIO(val));
+ printf("ref_rate = %d\n",G_MC_REF_RATE(val));
+
+}
+
+void dumptiming1(uint64_t val)
+{
+ printf("w2rIdle = %d\n",(val & M_MC_w2rIDLE_TWOCYCLES) ? 1 : 0);
+ printf("r2rIdle = %d\n",(val & M_MC_r2rIDLE_TWOCYCLES) ? 1 : 0);
+ printf("r2wIdle = %d\n",(val & M_MC_r2wIDLE_TWOCYCLES) ? 1 : 0);
+ printf("tCrD = %d\n",(int)G_MC_tCrD(val));
+ printf("tCrDh = %d\n",(val & M_MC_tCrDh) ? 1 : 0);
+ printf("tFIFO = %d\n",(int)G_MC_tFIFO(val));
+ printf("tCwD = %d\n",(int)G_MC_tCwD(val));
+
+ printf("tRP = %d\n",(int)G_MC_tRP(val));
+ printf("tRRD = %d\n",(int)G_MC_tRRD(val));
+ printf("tRCD = %d\n",(int)G_MC_tRCD(val));
+
+ printf("tRFC = %d\n",(int)G_MC_tRFC(val));
+ printf("tRCw = %d\n",(int)G_MC_tRCw(val));
+ printf("tRCr = %d\n",(int)G_MC_tRCr(val));
+ printf("tCwCr = %d\n",(int)G_MC_tCwCr(val));
+}
+
+int main(int argc,char *argv[])
+{
+ spdbyte_t *sf;
+ uint8_t t;
+ int idx;
+ int mclk;
+ draminittab_t *init;
+
+ spd[JEDEC_SPD_MEMTYPE] = JEDEC_MEMTYPE_DDRSDRAM2;
+ spd[JEDEC_SPD_ROWS] = 13;
+ spd[JEDEC_SPD_COLS] = 9;
+ spd[JEDEC_SPD_BANKS] = 2;
+ spd[JEDEC_SPD_SIDES] = 1;
+ spd[JEDEC_SPD_WIDTH] = 72;
+
+ argc = proc_args(argc,argv);
+
+ if ((argc == 1) && !swisset("-i")) {
+ printf("usage: memconfig name=value name=value ...\n");
+ printf("\n");
+ printf("Available fields: ");
+ sf = spdfields;
+ while (sf->name) {
+ printf("%s ",sf->name);
+ sf++;
+ }
+ printf("\n");
+ exit(1);
+ }
+
+ if (swisset("-i")) {
+ interactive();
+ }
+ else {
+ for (idx = 1; idx < argc; idx++) {
+ if (procfield(argv[idx]) < 0) exit(1);
+ }
+ }
+
+ debug = swisset("-d");
+
+ printf("-------Memory Parameters---------\n");
+
+ sf = spdfields;
+ while (sf->name) {
+ char buffer[64];
+ char *p = buffer;
+
+ t = *(sf->data);
+ printf("%-10.10s = 0x%02X ",sf->name,t);
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ p += sprintf(p,"(%d.%d)",
+ t >> 4, t & 0x0F);
+ break;
+ case SPD_DEC_QTR:
+ p += sprintf(p,"(%d.%02d)",
+ t/4,(t&3)*25);
+ break;
+ case SPD_ENCODED:
+ p += sprintf(p,"(%s)",lookupstr(sf->values,t));
+ break;
+ default:
+ p += sprintf(p,"(%d)",t);
+ break;
+ }
+
+ p += sprintf(p," %s",sf->units);
+ printf("%-16.16s %s\n",buffer,sf->description);
+ sf++;
+ }
+
+ printf("\n");
+
+ init = &inittab[0];
+ memset(inittab,0,sizeof(inittab));
+
+ init->gbl.gbl_type = MCR_GLOBALS;
+ init->gbl.gbl_intlv_ch = portintlv;
+ init++;
+
+ init->cfg.cfg_type = MCR_CHCFG;
+ init->cfg.cfg_chan = 0;
+ init->cfg.cfg_mintmemclk = mintmemclk;
+ init->cfg.cfg_dramtype = dramtype;
+ init->cfg.cfg_pagepolicy = CASCHECK;
+ init->cfg.cfg_blksize = BLKSIZE32;
+ init->cfg.cfg_intlv_cs = NOCSINTLV;
+ init->cfg.cfg_ecc = 0;
+ init->cfg.cfg_roundtrip = roundtrip;
+ init++;
+
+ init->clk.clk_type = MCR_CLKCFG;
+ init->clk.clk_addrskew = addrskew;
+ init->clk.clk_dqoskew = dqoskew;
+ init->clk.clk_dqiskew = dqiskew;
+ init->clk.clk_addrdrive = addrdrive;
+ init->clk.clk_datadrive = datadrive;
+ init->clk.clk_clkdrive = clkdrive;
+ init++;
+
+ init->geom.geom_type = MCR_GEOM;
+ init->geom.geom_csel = 0;
+ init->geom.geom_rows = spd[JEDEC_SPD_ROWS];
+ init->geom.geom_cols = spd[JEDEC_SPD_COLS];
+ init->geom.geom_banks = spd[JEDEC_SPD_BANKS];
+ init++;
+
+#if 0
+ init->tmg.tmg_type = MCR_TIMING;
+ init->tmg.tmg_tCK = spd[JEDEC_SPD_tCK25];
+ init->tmg.tmg_rfsh = spd[JEDEC_SPD_RFSH];
+ init->tmg.tmg_caslatency = spd[JEDEC_SPD_CASLATENCIES];
+ init->tmg.tmg_attributes = spd[JEDEC_SPD_ATTRIBUTES];
+ init->tmg.tmg_tRAS = spd[JEDEC_SPD_tRAS];
+ init->tmg.tmg_tRP = spd[JEDEC_SPD_tRP];
+ init->tmg.tmg_tRRD = spd[JEDEC_SPD_tRRD];
+ init->tmg.tmg_tRCD = spd[JEDEC_SPD_tRCD];
+ init->tmg.tmg_tRFC = spd[JEDEC_SPD_tRFC];
+ init->tmg.tmg_tRC = spd[JEDEC_SPD_tRC];
+ init++;
+#else
+ init->spd.spd_type = MCR_SPD;
+ init->spd.spd_csel = 0;
+ init->spd.spd_flags = 0;
+ init->spd.spd_smbuschan = 0;
+ init->spd.spd_smbusdev = 0x50;
+ init++;
+#endif
+
+ init->mcr.mcr_type = MCR_EOT;
+
+
+ sb1250_refclk = (int) refclk;
+
+ sb1250_dram_init(inittab);
+
+
+ printf("-----Memory Timing Register Values-----\n");
+ printf("System Clock %dMHz\n",plldiv*refclk/2);
+ printf("CAS latency %d.%d\n",dram_cas_latency>>1,(dram_cas_latency&1)?5:0);
+ printf("tMemClk %d.%d ns\n",dram_tMemClk/10,dram_tMemClk%10);
+ mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc0_mclkcfg));
+ printf("MCLK Freq %d.%dMHz\n",mclk/10,mclk%10);
+ printf("\n");
+ printf("MC_TIMING1 = %016llX\n",mc0_timing1);
+ printf("MCLK_CONFIG = %016llX\n",mc0_mclkcfg);
+ printf("\n");
+
+ printf("-----Memory Timing Register Fields-----\n");
+ dumptiming1(mc0_timing1);
+
+ printf("-----Memory Clock Config Register Fields-----\n");
+ dumpmclkcfg(mc0_mclkcfg);
+
+ printf("---Done!---\n");
+
+ printf("%s ",argv[0]);
+ sf = spdfields;
+ while (sf->name) {
+ char buffer[64];
+ char *p = buffer;
+
+ t = *(sf->data);
+
+ p += sprintf(p,"%s=",sf->name);
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ p += sprintf(p,"%d.%d",
+ t >> 4, t & 0x0F);
+ break;
+ case SPD_DEC_QTR:
+ p += sprintf(p,"%d.%02d",
+ t/4,(t&3)*25);
+ break;
+ case SPD_ENCODED:
+ default:
+ p += sprintf(p,"0x%02X",t);
+ break;
+ }
+
+ printf("%s ",buffer);
+ sf++;
+ }
+
+ printf("\n");
+
+ return 0;
+}